首页 » Android layout inflation 优化

Android layout inflation 优化

减少布局的嵌套层级

使用 ConstraintLayout 代替多层嵌套的 LinearLayout

异步加载

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);
}

10次 inflate 约耗时12ms,使用 AsyncLayoutInflater 异步 inflate 后,这部分的耗时操作就不再占用主线程。

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);
}

懒加载

页面上有些 view 只在部分情况下才显示,比如:

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

针对这些 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
}

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注