通常我们会在布局中编写大量的View,而安卓在加载这些View的时候会遍历解析所有的xml节点,然后通过反射创建对应的View实例,这些都是在主线程中进行的。
如果说我们的布局文件嵌套很深,或者有大量的View控件,就会导致布局的加载缓慢。谷歌提供了在子线程中加载布局思路,它是一种异步加载布局的方式。

接下来分析下源码:

AsyncLayoutInflater源码非常简单,一共200多行,先来看下构造方法。

初始化了mInflater,mHandler,mInflateThread。

1 BasciInflater继承LayoutInflater,重写了onCreateView,优先加载这三个前缀的"android.widget.","android.webkit.","android.app."的Layout,然后再按照默认的流程去加载,因为布局常用的View都在这三个包下。
2 创建Handler就是为了切换线程,AsyncLayoutInflater是在异步里解析布局,那创建回来的View对象需要回调给主线程,就是通过Handler来实现的。
3 InflateThread这个是一个线程,是来做解析布局的工作线程,

通过InflateThread.getInstance可以猜测这个是一个单例,默认只在一个线程中做所有的加载工作。
接下来我们分析inflate方法

首先会通过InflateThread去获取一个InflateRequest,

从对象池中取一个对象,节约创建对象开销的内存。

接下来就是对inflateRequest变量赋值之后会将其加到InflateThread中的一个队列中等待执行。


1 静态代码块,确保只会创建一次,并且创建就马上调用start方法。
2 异步inflate缓存队列有界阻塞队列数组大小为10
3 request = mQueue.take();从队列中取一个request
4 mQueue.put(request);// 添加到缓存队列中添加到缓存队列中去
5 Message.obtain(request.inflater.mHandler,0, request) .sendToTarget();// 通过Handler回调到主线程执行
enqueue函数:只是插入元素到mQueue队列中,如果元素过多那么是有排队机制的。
runInner函数:运行于循环中,从mQueue队列取出元素,调用inflate方法,通过handler回调到主线程。
在代码中发现runInner运行在循环中,会一直执行吗?
答案不会。mQueue队列的类型是ArrayBlockingQueue,这是一个“生产者-消费者模型”,如果队列中没有元素,那么mQueue.take()就会处于等待状态,直到mQueue.put到队列中有元素了后唤醒才会继续执行。
网友评论