一文了解 Android 布局加载原理

694 阅读2分钟

屏幕截图 2024-06-30 104501.png

Android 的布局加载原理

  1. 首页调用 ActivitysetContentView 方法,内部最后调用到了 AppCompatDelegateImplsetContentView 方法。
  2. 上面有两种情况,一种是直接设置的 View,一种是设置 layout.id。但是无论是哪种情况,从 xml 转化到对应的 Java 文件,都需要走到 LayoutInflaterinflate 方法。
  3. inflate 方法中先会创建 XmlResourceParser 对象,它的作用就是解析 xml 标签
  4. 然后判断开始标签是否为 merge,如果不是,则先使用 createViewFromTag 创建父标签对象;否则直接调用 rInflate 方法以循环遍历的方式来创建 View 对象。需要注意的是,rInflate 方法内部,也是通过 createViewFromTag 方法来创建对应的 View 的
  5. createViewFromTag 方法中,我们首先会先判断 Factory2 是否存在,如果存在就调用它的 createView 方法;否则判断 Factory 是否存在,如果存在就调用它的 createView 方法。如果都不存在就会调用默认的 Factory2createView 方法。在该方法中是通过反射来实现创建 view 对象的。
  6. rInflate 方法中,通过 createViewFromTag 方法创建完所有的 view 对象后,整个布局加载流程就结束了。

性能瓶颈

从上面的 Android 的布局加载原理中可以看出,布局加载流程主要有两个性能的瓶颈:

  1. 布局文件加载过程。布局加载过程是一个IO操作,如果 xml 布局太大,就会拖慢View的创建速度。
  2. 创建View对象过程。默认情况下,创建对象是通过反射实现,如果需要创建的 View 非常多,也会影响性能

优化

上面分析到,Android 的布局加载原理主要有两个。因此,我们就可以从这两方面来优化这个问题。

  1. 设置 FactoryFactory2,从上面的加载原理可以知道,Android 会先判断 FactoryFactory2 是否存在,如果存在就直接使用它的 createView 方法,这样就不会使用反射来调用了。
  2. 不使用 xml 来创建布局,而是通过 java 来直接创建,但是这种方式不便于开发,可维护性差。我们还可以通过 x2c 框架来实现,它会编译区间编译成Java代码,但是它也有不足的地方,比如说部分属性Java不支持
  3. 由于布局加载是一个 IO 过程,我们可以让它在子线程去执行,不阻塞主线程。在 Android 中提供了 AsyncLayoutInflater 来实现这个效果。但是它也有两个缺陷,一个是他最多可以处理 10 个加载任务,超过 10个的任务还是会在主线程执行;另一个是,它无法设置 Factory
  4. 其他的优化手段,就只有从层级入手了。比如说,使用 merge 标签,减少一层嵌套;使用 ConstraintLayout 替代 RelativeLayout 或者 LinearLayout等等