美文网首页
Layout inflation 优化

Layout inflation 优化

作者: CrazyOrr | 来源:发表于2020-03-03 14:08 被阅读0次
  • 减少布局的嵌套层级

  • 异步加载

    AsyncLayoutInflater

    ViewGroup动态添加子View时,我们往往使用一个layout的XML来inflate一个view,然后将其add到父容器。
    inflate包含对XML文件的读取和解析(IO操作),并通过反射创建View树。当XML文件过大或页面层级过深,布局的加载就会较为耗时。
    由于这一步并非UI操作,可以转移到非主线程执行,为此,官方在扩展包提供了AsyncLayoutInflater

    以inflate一个简单的layout 10次为例:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:context=".jank.JankActivity">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="hello" />
    </FrameLayout>
    
    for (int i = 0; i < 10; i++) {
        layoutInflater.inflate(R.layout.view_jank, container, false);
    }
    

    同步inflate约需耗时12ms。

    AsyncLayoutInflater asyncLayoutInflater = new AsyncLayoutInflater(this);
    AsyncLayoutInflater.OnInflateFinishedListener onInflateFinishedListener = new AsyncLayoutInflater.OnInflateFinishedListener() {
        @Override
        public void onInflateFinished(@NonNull View view, int resid, @Nullable ViewGroup parent) {
            if (parent != null) {
                parent.addView(view);
            }
        }
    };
    
    for (int i = 0; i < 10; i++) {
        asyncLayoutInflater.inflate(R.layout.view_jank, container, onInflateFinishedListener);
    }
    

    使用AsyncLayoutInflater异步inflate后,主线程就不再有inflate的耗时了。

    适用场景:动态加载layout较复杂的view

  • 懒加载

    ViewStub

    <ViewStub
        android:id="@+id/stub"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout="@layout/real_view" />
    
    ViewStub stub = findViewById(R.id.stub);
    if (stub != null) {
        stub.inflate(); // inflate一次以后,view树中就不再包含这个ViewStub了
    }
    

    适用场景:只在部分情况下才显示的View

    例如:

    • 网络请求失败的提示
    • 列表为空的提示
    • 新内容、新功能的引导,因为引导基本上只显示一次
  • 延迟加载

    IdleHandler

    Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
        @Override
        public boolean queueIdle() {
            // 当该Looper线程没有message要处理时才执行
            return false;
        }
    });
    

    在主线程注册回调,当主线程"空闲"时才执行回调中的逻辑。

    适用场景:非必需的页面元素的加载和渲染,比如未读信息的红点、新手引导等。

相关文章

网友评论

      本文标题:Layout inflation 优化

      本文链接:https://www.haomeiwen.com/subject/ngiclhtx.html