Android中的Handler源码
1. 创建Message
val message = handler1.obtainMessage()
Message()
handler1.sendMessage(message)
handler1.post {}
在handler1.obtainMessage()
,这是复用已创建了的Message
public final Message obtainMessage()
{
return Message.obtain(this);
}
public static Message obtain(Handler h) {
Message m = obtain();
//在这里可以看出Message的实例会获取需要发送的Handle实例
m.target = h;
return m;
}
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
这里官方解释
Return a new Message instance from the global pool. Allows us to avoid allocating new objects in many cases.
从全局池中返回一个新的Message实例。允许我们在许多情况下避免分配新对象。
我们自己也能看出从sPool的消息池中获取到Message实例,没有则创建一个新的,Message空白构造函数什么都没干。
2. 发送消息
handler1.sendMessage(message)
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
这里可以看出两种传递消息的方法都调用sendMessageDelayed
,只是post
中使用了getPostMessage(r)
来获取了一个Message实例。
// 创建一个具有callback的Message,
// 具有callback的在dispatchMessage会执行callback内的内容。
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
这里可以看出Message中多了一个Runnable实例。
当
callback
字段被设置时,Handler
处理消息时会调用这个Runnable
对象的run()
方法,从而执行一些额外的操作。
使用callback
字段可以实现一些灵活的消息处理机制,例如:
- 延迟执行操作: 可以在
Message
中设置callback
,然后延迟一段时间发送这个消息,以便在指定的时间执行相应的操作。- 在特定条件下执行操作: 当某个条件满足时,可以发送带有
callback
的消息,在run()
方法中检查条件是否满足,然后执行相应的操作。- 执行耗时操作: 可以将一些耗时的操作封装在
callback
中,在Handler
的处理线程中执行,以避免阻塞 UI 线程。- 动态修改消息处理逻辑: 可以动态地修改消息的处理逻辑,通过改变
callback
对象,使得Handler
处理消息的方式发生变化。
在使用callback
字段时,需要注意避免内存泄漏问题,确保callback
对象的生命周期不会长于需要的时间,并在不需要时及时清除。
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
// 在这里获取了当前时间加自己延迟的时间,SystemClock.uptimeMillis() + delayMillis
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) {
//这里也能看出Message的target持有Handler实例
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
boolean enqueueMessage(Message msg, long when) {
......
synchronized (this) {
......
msg.markInUse();
// 这里将发送的时间存入message中
msg.when = when;
Message p = mMessages;
boolean needWake;
// message采用链表形式,并且根据when的大小来确定插入消息队列的位置
// 这里是判断将发送的msg放入链表头
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
.....
// 这里找到位置并插入
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
这一流程可以看出发送消息中,会将handler实例存入message的target,有Runnable的也放入message中。消息队列是单链表,消息顺序是字段when决定的,when是在发消息时系统启动时间加上延迟时间。
MessageQueue是一个优先级队列是因为enqueueMessage方法中会根据Message的执行时间来对消息插入,这样越晚也就是when越大执行的消息会被插入到队列的后边。
public static void loop() {
final Looper me = myLooper();
.......
me.mInLoop = true;
......
// 这里死循环来分发消息队列中的消息
for (;;) {
if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
}
}
3. 线程切换
在loopOnce
时间原因只理解了201行的msg.target.dispatchMessage(msg);
由于target是发送消息的Handler,在Handler中会根据Looper中的线程来发送到目的线程。
// 这里传入的是主线程的looper,looper中有MessageQueue的实例也会传入handler中
val handler1 = object: Handler(Looper.getMainLooper()){}
public Handler(@NonNull Looper looper) {
this(looper, null, false);
}
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
默认情况下,Handler 的 dispatchMessage() 方法会简单地调用消息对象中的 callback,如果 callback 不为 null,则执行 callback 的 run() 方法。如果 callback 为 null,则会调用 handleMessage(Message msg) 方法。
dispatchMessage() 方法的源代码通常不需要开发者自行实现,因为 Handler 类已经提供了默认实现。开发者通常只需重写 handleMessage(Message msg) 方法,来实现自定义的消息处理逻辑。但是,如果有特定需求,也可以重写 dispatchMessage() 方法,以实现更灵活的消息处理机制。
接下来解决线程切换问题
在Looper类中维持着
static final ThreadLocal<Looper> sThreadLocal =
new ThreadLocal<Looper>();
private static Looper sMainLooper;
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
//每一个线程只能调用一次prepare()
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
可以看出每一个线程只维持这一个Looper,但是其中始终包含了一个主线程Looper在其中
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
4. 其他创建一个Looper
thread {
Looper.prepare()
val messageQueue = MessageQueue()
val handler2 = object: Handler(Looper.myLooper()!!){
override fun dispatchMessage(msg: Message) {
super.dispatchMessage(msg)
}
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
}
}
Looper.loop
Log.i("TAG", "onCreate: ${handler2.looper}")
}