一、写在前面
Android系统在设计之初被设计成单线程模型,其实不仅仅是Android
,像Java Swing都使用了单线程模型,这也是有历史原因的。回到Android
中,都知道只能在UI线程也即主线程中更新UI,并且规定了UI线程中不能够进行耗时操作(5S),像网络请求,I/O操作等。否则会出现ANR,程序无响应。作为开发这是最不愿意看的。那么实际开发中肯定也会有需要在子线程更新UI的场景,可以说Handler也是为了解决这一矛盾的-只能在UI线程中更新UI。官方注释中同样给出了Handler
两大主要作用:
1.To schedule messages and runnables to be executed at some point in the future;
2.To enqueue an action to be performed on a different thread than your own.
二、带着问题看
Android上线源码阅读工具(Android Code Search)后查看源码相比于之前算是极大的方便了,可以看到最新版本的源码信息,同样也支持调用之间的跳转;几乎跟Android Studio相差无几了。如图,可以根据需要选择想要查看的源码版本:
就自身而言,无论是Android的系统源码还是其他优秀开源库的源码的阅读,在准备阅读之前都会整理出自己想要了解的方向或者问题,这样带着问题去看,优先看与问题相关的内容。个人认识还是比较高效的,毕竟系统源码设计细节太过于复杂,深陷细节当中往往达不到整体把握的效果。那么常见的问题或者说作为上层App
开发应该需要掌握哪些内用与细节呢?
三、常见问题
1.一个线程有几个Handler?
2.一个线程有几个Looper?如何保证?
3.一个线程可以有几个MessageQueue?
4.如何创建一个Message对象?
5.Handler内存泄漏的根本原因?内部类是不是都会导致内存泄漏?
6.主线程中如何实例化一个Handler对象,子线程中呢?
7.Looper死循环为什么不会导致应用ANR,会消耗资源吗?
8.子线程中维护Looper,消息队列无消息时如何处理?有什么用?
9.使用Handler的postDelay后消息队列的变化?
10.多个Handler如何保证线程安全?
11.什么是同步屏障,有什么作用,同步屏障与异步消息的具体使用场景?
12.Android IdleHandler应用场景?
13.可以多次创建Looper对象嘛?
14.MessageQueue作用,数据结构?
15.延迟消息的实现?
16.pipe/epoll机制?
简单的总结了一些需要掌握的问题,带着这些问题看源码的具体实现,做到心中有数。当然重点还是要关注Handler、Message、Looper这套机制的具体实现细节。基于源码Android-12.0.0_r4
。
1.Handler具体实现
消息的的处理类,主要的职责是发送消息到“消息队列”,并处理消息。
- 构造函数:
@Deprecated
public Handler() {
this(null, false);
}
@Deprecated
public Handler(@Nullable Callback callback) {
this(callback, fasle);
}
public Handler(@NonNull Looper looper) {
this(looper, null, false);
}
public Handler(@NonNull Looper looper, @Nullable Callback callback) {
this(looper, callback, false);
}
@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//.....
在最新的源码之中,关于构造函数中不带Looper参数的方法已经被打上**@Deprecated的标签,官方已经不建议这样实例化出一个Handler**对象(隐式的指定Looper对象),源码给出的解释:
Implicitly choosing a Looper during Handler construction can lead to bugs where operations are silently lost (if the Handler is not expecting new tasks and quits) crashes .
先不具体深究,继续往下看Handler其他比较重要的方法有哪些。
- 方法处理handleMessage()
//Subclasses must implement this to receive messages.
public void handleMessage(@NonNull Message msg) {
//空方法,实现类需要处理用来接收信息
}
//Callback interface you can use when instantiating a Handler to avoid
//having to implement your own subclass of Handler.
public interface Callback {
boolean handleMessage(@NonNull Message msg);
}
方法处理比较简单,一个Callback接口,当然可以在实例化Handler的作为参数传入,同时包含一个handleMessage的空方法,需要子类自己实现具体的消息处理细节。
- 消息的分发
//Handle system messages here.
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(@NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
//@hide
public final boolean postDelayed(Runnable r, int what, long delayMillis) {
return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);
}
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what) {
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);