美文网首页
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