android 19源码,Android源码系列(19)

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

一、类签名

这是用于异步填充 View 的帮助类。在主线程构建 AsyncLayoutInflater 实例,并调用方法 inflate(int, ViewGroup, OnInflateFinishedListener)。视图填充完毕后在主线程回调 OnInflateFinishedListener 通知调用者。

public final class AsyncLayoutInflater

这适用于懒创建或响应用户交互的UI部分。有利于主线程继续响应用户时,重量级填充操作继续执行。填充布局需要来自 ViewGroup.generateLayoutParams(AttributeSet) 的父布局,该方法线程安全。所有视图在构建过程中,禁止创建任何 Handler 或调用 Looper.myLooper() 。若布局无法在子线程进行异步填充,则操作会回退到主线程上执行。

注意,视图填充完成后不会加入到父布局中。这相当于调用 LayoutInflater.inflate(int, ViewGroup, boolean) 时参数 attachToRoot 为 false。因为调用者很可能希望在 OnInflateFinishedListener 通过调用 ViewGroup.addView(View) 把视图放入父布局。

本填充器不支持设置 LayoutInflater.Factory 或 LayoutInflater.Factory2。类似,也不支持填充包含 fragment 的布局。源码版本Android 28

二、数据成员

// 负责填充的LayoutInflater实例

LayoutInflater mInflater;

// Handler

Handler mHandler;

// 线程

InflateThread mInflateThread;

如果请求在子线程填充的过程中出现异常,则任务会派发到主线程重试一次

private Callback mHandlerCallback = new Callback() {

@Override

public boolean handleMessage(Message msg) {

// 获取填充请求,进行视图的填充,以下操作都在主线程进行

InflateRequest request = (InflateRequest) msg.obj;

if (request.view == null) {

request.view = mInflater.inflate(

request.resid, request.parent, false);

}

// 填充成功,触发回调

request.callback.onInflateFinished(

request.view, request.resid, request.parent);

// 填充完成,回收请求以便以后复用

mInflateThread.releaseRequest(request);

return true;

}

};

三、构造方法

构造方法内初始化了实际负责填充工作的填充器 BasicInflater。

public AsyncLayoutInflater(@NonNull Context context) {

mInflater = new BasicInflater(context);

// 由于Handler在主线程创建,所以内部默认使用主线程

mHandler = new Handler(mHandlerCallback);

mInflateThread = InflateThread.getInstance();

}

四、成员方法

主线程通过此方法添加新填充任务。

@UiThread

public void inflate(@LayoutRes int resid, @Nullable ViewGroup parent,

@NonNull OnInflateFinishedListener callback) {

// 回调不能为空,以便把填充完成的布局返回给调用者

if (callback == null) {

throw new NullPointerException("callback argument may not be null!");

}

// 从缓存池中获取一个空的填充请求

InflateRequest request = mInflateThread.obtainRequest();

// 把填充需要的数据存入填充请求中

request.inflater = this;

request.resid = resid;

request.parent = parent;

request.callback = callback;

// 请求添加到子线程等待处理

mInflateThread.enqueue(request);

}

五、OnInflateFinishedListener

在子线程处理完毕后,通过此回调把填充完成的 View 返回给调用者。创建完成的 View 需要调用者自行添加到 ViewGroup 中,而不能像普通 LayoutInflater 那样直接加入到父布局。

public interface OnInflateFinishedListener {

void onInflateFinished(@NonNull View view, @LayoutRes int resid,

@Nullable ViewGroup parent);

}

六、InflateRequest

这个为构建任务的请求,请求包含参数:用于测绘的父布局、资源id、回调监听、已填充视图。初始化完成后的请求放入 InflateThread 的阻塞队列等待处理。

private static class InflateRequest {

// AsyncLayoutInflater

AsyncLayoutInflater inflater;

// 父布局

ViewGroup parent;

// 需填充资源的id

int resid;

// 填充完成的视图,未填充完成为null

View view;

// 填充完成的回调

OnInflateFinishedListener callback;

InflateRequest() {

}

}

七、BasicInflater

此类继承父类 LayoutInflater 并重写父类方法 onCreateView(String name, AttributeSet attrs)。在此方法内,调用父类方法 createView 反射构建目标视图。

先尝试用 sClassPrefixList 的前缀构建视图,因为使用的视图多数位于这三个包路径底下。

private static class BasicInflater extends LayoutInflater {

private static final String[] sClassPrefixList = {

"android.widget.",

"android.webkit.",

"android.app."

};

BasicInflater(Context context) {

super(context);

}

@Override

public LayoutInflater cloneInContext(Context newContext) {

return new BasicInflater(newContext);

}

@Override

protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {

for (String prefix : sClassPrefixList) {

try {

// 构建视图

View view = createView(name, prefix, attrs);

if (view != null) {

return view;

}

} catch (ClassNotFoundException e) {

// In this case we want to let the base class take a crack

// at it.

}

}

// 填充的视图不在以上三个包内,则调用父类方法构建

return super.onCreateView(name, attrs);

}

}

八、InflateThread

负责填充视图的线程。线程内包含任务阻塞队列,这个队列的空间为10。当放入任务数量超过10时,如果主线程继续放入新任务,则主线程会被阻塞直到队列出现空余位置。这个类是单例,所以多个 AsyncLayoutInflater 实例共享一个工作线程及内部线程池。

如果有非常多任务需要异步填充,由于每个填充的视图平均需要10ms的时间,所以会出现视图排队填充完成,造成长时间等待。

private static class InflateThread extends Thread {

private static final InflateThread sInstance;

static {

sInstance = new InflateThread();

sInstance.start();

}

public static InflateThread getInstance() {

return sInstance;

}

// 等待处理InflateRequest实例的阻塞队列

private ArrayBlockingQueue mQueue = new ArrayBlockingQueue<>(10);

// 复用InflateRequest实例的缓存池

private SynchronizedPool mRequestPool = new SynchronizedPool<>(10);

// Extracted to its own method to ensure locals have a constrained liveness

// scope by the GC. This is needed to avoid keeping previous request references

// alive for an indeterminate amount of time, see b/33158143 for details

public void runInner() {

InflateRequest request;

try {

// 从队列获取等待任务

request = mQueue.take();

} catch (InterruptedException ex) {

// Odd, just continue

Log.w(TAG, ex);

return;

}

try {

// 从InflateRequest取出资源id、父布局样式作为参数,通过BasicInflater构建视图

request.view = request.inflater.mInflater.inflate(

request.resid, request.parent, false);

} catch (RuntimeException ex) {

// Probably a Looper failure, retry on the UI thread

Log.w(TAG, "Failed to inflate resource in the background! Retrying on the UI"

+ " thread", ex);

}

Message.obtain(request.inflater.mHandler, 0, request)

.sendToTarget();

}

// 循环从阻塞队列中获取任务

@Override

public void run() {

while (true) {

runInner();

}

}

// 从缓存池中获取一个有效InflateRequest用于构建任务参数

public InflateRequest obtainRequest() {

// 先尝试从缓存池中获取对象

InflateRequest obj = mRequestPool.acquire();

if (obj == null) {

// 若缓存池没有缓存对象才创建新对象

obj = new InflateRequest();

}

return obj;

}

// 填充任务完成后,释放InflateRequest并放回缓存池中等待复用

public void releaseRequest(InflateRequest obj) {

obj.callback = null;

obj.inflater = null;

obj.parent = null;

obj.resid = 0;

obj.view = null;

// 已重置对象放回缓存池

mRequestPool.release(obj);

}

// 初始化完成的任务通过此方法放入队列等待处理

public void enqueue(InflateRequest request) {

try {

mQueue.put(request);

} catch (InterruptedException e) {

throw new RuntimeException(

"Failed to enqueue async inflate request", e);

}

}

}

九、缺点不支持多线程并发处理任务;

类修饰为 final,不能通过继承重写父类实现;

任务等待队列不能自定义初始化大小;

不支持设置 LayoutInflater.Factory 或 LayoutInflater.Factory2;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值