type
status
date
slug
summary
tags
category
icon
password

两种资源

  • 预编译的layout资源(dex文件)
  • xml layout文件

预编译的布局

目前的版本(Android 11)并没有开放这个功能.
基本的处理流程如下:
  1. 使用view_compiler将xml布局直接编译成CompiledView.java文件;
    1. 源码地址: view_compiler
      整个app的预编译layout资源最后会打包到compiled_view.dex文件中;
  1. 在需要渲染xml布局的地方使用CompiledView.infalte替代

xml布局

看了上面这部分的代码,逻辑算是比较清晰的了:
  1. 获取Resources对象,通过Resources对象获取到与resourceId绑定的XmlResourceParser对象;
  1. 使用XmlResourceParser解析XML Layout结构;
  1. 先获取到根节点(即第一个START TAG),然后进行递归遍历,先搞定内部嵌套的的结构,再搞定外部的结构;
  1. 从XML Tag创建View的过程中间可以通过Factory/Factory2等进行代理/拦截,如果不做处理,则会使用反射进行创建;

从XML TAG 到 View

如果不设置各种Factory,则最终会调用LayoutInflater的createView()方法,从XML tag通过反射创建View对象;
主要步骤如下:
  1. 找到或者创建对应的Constructor;
  1. 进行Filter拦截处理,判断是否允许对应的View被加载成类;
  1. 使用Constructor通过反射创建View对象;
  1. 如果创建的View对象是ViewStub,则将当前的LayoutInflater设置给它;
其实分析到这里还有几个关键问题没有提及到:
  • XmlResourceParser是如何创建的?作为一个XmlPullParser的实现,又是在哪设置的输入,将xml文件输入到API中的?
  • Android Layout文件中View的各种属性是如何与对应View进行绑定的,或者说是暂时存储在哪的?

XmlResourceParser的创建

在Resources中有:
在ResourcesImpl中有:
这里再看看XMLBlock的创建:
XMLBlock中有:
frameworks/base/core/jni/android_util_AssetManager.cpp中有:
到这里可以看到流程如下:
  1. C++层通过assetmanager根据resId + DynamicRefTable获取到对应资源文件的buffer和大小,并将数据设置到ResXmlTree中,并返回其地址,作为Java层的XmlBlock;
  1. Java层中XmlResourcesParser的解析工作其实是通过XmlBlock中的内部类Parser去完成的,而XmlBlock层中有来自于C++层的ResXmlTree的地址,因此刚刚好可以用来读取布局数据;

XmlBlock中的解析

看下next()方法实现就差不多了,其他很多方法都在C++层,这里只需要知道XmlResourcesParser的实现类其实是XmlBlock中的Parser即可;

Layout文件中属性的绑定

其实前面在解析的时候有下面这一句:
因为XmlResourcesParser本身就是实现的AttributeSet,因此可以进行转换;
然后这个AttributeSet会在加载渲染的过程中传递给View.主要有两个用途:
  • 设置布局的layout_width/layout_height
    • 在反射创建View的时候作为参数传入
      • 可以看到反射一定会调用到View(Context,AttributeSet);这个时候会传入Context参数和AttributeSet参数.便于View去处理各种属性.
    Kotlin中的协程Java中的ThreadPoolExecutor
    Loading...