内容简介:这是用于异步填充这适用于懒创建或响应用户交互的UI部分。有利于主线程继续响应用户时,重量级填充操作继续执行。填充布局需要来自注意,视图填充完成后不会加入到父布局中。这相当于调用
一、类签名
这是用于异步填充 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);
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 反射构建目标视图。
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<InflateRequest> mQueue = new ArrayBlockingQueue<>(10);
// 复用InflateRequest实例的缓存池
private SynchronizedPool<InflateRequest> mRequestPool = new SynchronizedPool<>(10);
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 ;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【源码阅读】AndPermission源码阅读
- ReactNative源码解析-初识源码
- 【源码阅读】Gson源码阅读
- Spring源码系列:BeanDefinition源码解析
- istio 源码 – Citadel 源码分析 (原创)
- istio 源码 – pilot 源码分析(原创)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C++设计新思维
(美)Andrei Alexandrescu / 侯捷、於春景 / 华中科技大学出版社 / 2003-03 / 59.8
本书从根本上展示了generic patterns(泛型模式)或pattern templates(模式模板),并将它们视之为“在C++中创造可扩充设计”的一种功能强大的新方法。这种方法结合了template和patterns,你可能未曾想过,但的确存在。为C++打开了全新视野,而且不仅仅在编程方面,还在于软件设计本身;对软件分析和软件体系结构来说,它也具有丰富的内涵。一起来看看 《C++设计新思维》 这本书的介绍吧!
图片转BASE64编码
在线图片转Base64编码工具
HEX HSV 转换工具
HEX HSV 互换工具