Handler机制源码解析(二)

主要包括Handler其他使用知识点

Handler拓展知识

1. 子线程创建Handler对象

Handler-子线程创建Handler对象

不可以直接在子线程创建Handler对象,因为Handler对象必须要绑定一个Looper,才可以使用。

若在子线程需要使用Handler,则需要先创建一个Looper对象即执行Looper.prepare()然后再创建Handler对象时调用Looper.myLooper()获取Looper对象传入方法,最后调用Looper.loop()开始运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class MyActivity : Activity{
lateinit var mThread: MyThread
lateinit var mHandler: MyHandler

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.act_main)
//初始化子线程
mThread = Mythread()
mThread.start()
//需要发出的消息
val message = Message.obtain()
message.obj = "test"
//初始化Handler
mHandler = MyHandler(this, mThread.childLooper)+
//发送消息
mHandler.sendMessage(message)
}

//子线程
class MyThread : Thread() {
var childLooper: Looper? = null
override fun run() {
Looper.prepare()
childLooper = Looper.myLooper()
Looper.loop()
}
}

//安全的Handler写法
class MyHandler(activity: MyActivity, looper: Looper?) : Handler(looper) {
var mWeakRe: WeakReference<MyActivity> = WeakReference(activity)

override fun handleMessage(msg: Message?) {
super.handleMessage(msg)
val activity: MyActivity? = mWeakRe.get()
if (activity!=null){
//添加handlerMessage需要处理的逻辑
}
}
}
}

以上代码执行完毕后就可以在子线程调用Handler对象。

但是,在多次执行过程中,会有java.lang.NullPointerException: Attempt to read from field ‘android.os.MessageQueue android.os.Looper.mQueue’ on a null object reference空指针导致应用崩溃。调试过程中发现是由于Looper对象为空导致的异常。由于在子线程run()初始化了Looper对象,Handler对象的初始化依然继续执行,Looper对象此时尚未初始化好,导致空指针异常。

由于这种情况的出现是随机的,不是百分百重现,为了保证应用的运行就需要引入HandlerThread这个类,可以帮我们解决这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//HandlerThread示例代码
class MyActivity : Activity{
lateinit var mHandler: MyHandler
var mHandlerThread: HandlerThread?=null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.act_main)
//初始化HandlerThread并指定线程名字为test
mHandlerThread = HandlerThread("test",Process.THREAD_PRIORITY_BACKGROUND)
mHandlerThread?.start()
//需要发出的消息
val message = Message.obtain()
message.obj = "test"
//初始化Handler
mHandler = MyHandler(this, mHandlerThread?.looper)
//发送消息
mHandler.sendMessage(message)
}

//安全的Handler写法
class MyHandler(activity: MyActivity, looper: Looper?) : Handler(looper) {
var mWeakRe: WeakReference<MyActivity> = WeakReference(activity)

override fun handleMessage(msg: Message?) {
super.handleMessage(msg)
val activity: MyActivity? = mWeakRe.get()
if (activity!=null){
//添加handlerMessage需要处理的逻辑
}
}
}

override fun onDestroy() {
super.onDestroy()
//结束时停止thread
mHandlerThread?.quit()
}
}

以上代码执行完毕后即在HandlerThread可以调用Handler对象。

我们需要从源码去分析为什么使用HandlerThread可以避免上述异常,是怎样一个机制实现的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// 源码位置:../core/java/android/os/HandlerThread.java
public class HandlerThread extends Thread {
...
//设置线程优先级 优先级主要分为UI线程和后台线程(Background)
int mPriority;
public HandlerThread(String name) {
super(name);
//默认标准App线程优先级
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}

public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}

//可以重写这个方法,在内部新建Handler对象
protected void onLooperPrepared() {
}

@Override
public void run() {
//获取到线程ID
mTid = Process.myTid();
//创建对应的Looper,MessageQueue对象
Looper.prepare();
synchronized (this) {
//对mLooper进行赋值
mLooper = Looper.myLooper();
//唤醒等待Looper赋值而阻塞的所有线程
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}

public Looper getLooper() {
//判断当前线程是否存活 关闭则返回空
if (!isAlive()) {
return null;
}

// If the thread has been started, wait until the looper has been created.
synchronized (this) {
//mLooper==null表明当前Looper对象尚未初始化
while (isAlive() && mLooper == null) {
try {
//调用线程等待 直至初始化完成 阻塞其他线程
wait();
} catch (InterruptedException e) {
}
}
}
//返回Looper对象
return mLooper;
}

//内嵌一个可以直接引用的Handler对象,外部可以直接使用
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}

//HandlerThread退出 同步于Looper.quit()
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}

//HandlerThread退出 同步于Looper.quitSafely()
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
}

总结:

  • HandlerThread内嵌了Handler,Looper,MessageQueue对象
  • HandlerThread内部使用wait(),notifyAll()等线程同步方式保证mLooper对象不会为空,wait()当Looper对象尚未初始化完成时阻塞其他线程,notifyAll()当mLooper对象不为空时,通知其他线程使用mLooper。

2. IdleHandler

Handler-IdleHandler

当Looper里面的Message暂时处理完毕即全部消息处理完毕或者阻塞等待新消息时会调用IdleHandler这个类去处理一些空闲时间的消息。

继承IdleHandler这个接口,需要设置queueIdle()的返回值。若返回false则调用一次后会移除,为true则继续持有,空闲时依然会调用。

概括就是:优先级别较低的Message,只有当Looper中没有消息要处理时,才会去处理IdleHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//使用示例代码
val message = Message.obtain()
message.obj = "1234"
handler.sendMessage(message)

val delayMessage=Message.obtain()
delayMessage.obj="12344"
handler.sendMessageDelayed(delayMessage,3000)

//子线程添加IdleHandler 限制API23以上使用
mHandlerThread?.looper?.queue?.addIdleHandler(OnceIdleHandler())
mHandlerThread?.looper?.queue?.addIdleHandler(ForeverIdleHandler())
//主线程添加IdleHandler
Looper.myQueue().addIdleHandler(OnceIdleHandler())
Looper.myQueue().addIdleHandler(ForeverIdleHandler())

//只使用一次的IdleHandler
class OnceIdleHandler : MessageQueue.IdleHandler {
override fun queueIdle(): Boolean {
LogUtils.e("idle once")
return false
}
}

//一直持续存在的IdleHandler
class ForeverIdleHandler : MessageQueue.IdleHandler {
override fun queueIdle(): Boolean {
LogUtils.e("idle forever")
return true
}
}

//需要移除IdleHandler 调用
Looper.myQueue().removeIdleHandler(OnceIdleHandler())
Looper.myQueue().removeIdleHandler(ForeverIdleHandler())

集成上述代码即可测试IdleHandler的使用,接下来要分析源码的实现以及使用场景。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// 源码位置:../core/java/android/os/MessageQueue.java
/**
* IdleHandler定义
* Callback interface for discovering when a thread is going to block
* waiting for more messages.
*/

public static interface IdleHandler {
/**
* Called when the message queue has run out of messages and will now
* wait for more. Return true to keep your idle handler active, false
* to have it removed. This may be called if there are still messages
* pending in the queue, but they are all scheduled to be dispatched
* after the current time.
*/

boolean queueIdle();
}
//mIdleHandlers 是ArrayList型 故可以重复添加
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
//往MessageQueue中添加一个IdleHandler对象
public void addIdleHandler(@NonNull IdleHandler handler) {
if (handler == null) {
throw new NullPointerException("Can't add a null IdleHandler");
}
synchronized (this) {
//添加IdleHandler是线程安全的
mIdleHandlers.add(handler);
}
}

//移除一个IdleHandler
public void removeIdleHandler(@NonNull IdleHandler handler) {
synchronized (this) {
mIdleHandlers.remove(handler);
}
}

//调用上述方法往mIdleHandlers添加或移除IdleHandler对象后 需要在next()方法中 去使用mIdleHandlers中的对象
Message next() {
//无限循环
for(;;){
...
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// 判断当前没有空闲线程可执行 则继续堵塞
mBlocked = true;
continue;
}

if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}

// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler

boolean keep = false;
try {
//获取继承接口定义的queueIdle()返回值 判定后续是否需要继续执行
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}

if (!keep) {
//不需要继续执行 则自动移除对象
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
}

3. Handler常见问题

1. 消息机制中的主要引用对象及其关系

Looper ,MessageQueue,Message,ThreadLocal,Handler

  1. Looper对象有一个MessageQueue,MessgaeQueue为一个消息队列来存储Message
  2. Message中带有一个Handler对象,从Looper中取出消息后,可以直接调用到Handler的相关方法
  3. Handler发送消息时会把自身封装进Message Message.ontain(Handler h ,int what,int arg1,int arg2,Object onj)
  4. Handler通过获取Looper对象中的MessageQueue插入消息来发送Message
  5. Looper创建对象时会把自己保存至ThreadLocal中,并提供一个public static Looper myLooper()方法来返回一个Looper对象

2. Android主线程不会因为Looper.loop()死循环卡死

当线程中的可执行代码执行完成后,线程生命周期便该终止,线程就要退出。通过死循环的方式可以保证线程一直存活。

简单来说就是循环里有阻塞阻塞的原理是利用Linux的管道机制(PIPE/EPOLL)机制实现,所以死循环不会一直执行,由于大部分时间都是没有消息的,所以主线程大部分处于休眠状态,也不会过度消耗CPU资源导致卡死。

先说明进程和线程的区别:

进程:每个app运行时首先会创建一个进程,该进程是由zygote fork出来的,用于承载运行app上的Activity/Service等组件。进程对于上层应用来说是完全透明的,目的是为了让App都运行在Android Runtimr。大多数情况下一个App运行在一个线程中,除非配置了Android:Process属性,或者通过native fork 进程。

线程:线程比较常见,每次new Thread().start()都会创建一个新线程。并且与当前App所在进程之间资源共享。在CPU看来进程或线程无非是一段可执行的代码,CPU采用CFS调度算法,保证每个task尽可能公平享有CPU时间片

拓展知识:CFS调度算法是一种完全公平调度算法,基本设计思路是根据各个进程的权重来分配运行时间**。

当进入死循环时又该如何处理其他事务呢?需要创建新的线程去处理

主线程进入Looper的死循环后,需要处理 activity的各个生命周期的回调函数执行(在同一个线程下,代码是按顺序执行的,如果死循环堵塞了,后续该如何执行)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//源码地址 android/app/ActivityThread.java 
public static void main(String[] args){
...
//Looper初始化
Looper.prepareMainLooper();
//new 一个ActivityThread并调用了attach方法
ActivityThread thread = new ActivityThread();
thread.attach(false);

if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}

if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}

// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");
}

源码中在初始化ActivityThread时也会初始化一个H类型的成员,它继承了Handler

源码中调用thread.attach(false)时,回去创建一个Binder进程(具体代指ApplicationThread,Binder的服务端,用于接收系统AMS发出来的事件),由Handler线程发送Message至主线程。

所以在主线程开启Looper死循环之前,就已经启动了一个Binder线程并且准备了H 这一个Handler类,就可以用于处理一些死循环之外的事务。仅需通过Binder线程向H发送消息即可

App运行过程

system_server进程即为系统进程,里面运行了大量的系统服务,比如上图提供了ApplicationThreadProxy以及ActivityManagerService,这两者都基于IBinder接口,都是Binder线程。

App进程即为我们常说的应用程序,主线程主要负责Activity等组件的生命周期以及UI绘制。每个App进程中至少会包括两个binder线程:ApplicationThread和ActivityManagerProxy

Binder用于不同进程间的通信,由一个进程的Binder客户端向另一个进程的服务端发送事务。

Handler则用于同一进程间不同线程的通信。

3.主线程的消息模型

Handler-主线程消息模型

上图中绘制出主线程(ActivityThread)是如何循环的,简单的文字表达就是

ActivityManagerService(AMS) ==直接调用==>ApplicationThreadProxy(ATP)==Binder==>ApplicationThread==Handler方式==>ActivityThread

主线程(ActivityThread)通过ApplicationThreadActivityManagerService进行进程间通信,AMS以进程间通信的方式完成ActivityThread的请求后回调ApplicationThread中的Binder方法。然后由ApplicationThreadActivityThread中的H发送消息,然后收到消息后 把处理逻辑发送至ActivityThread中去执行。

4.Message的触发统计

Message是在MessageQueue中进行存放,事件的分发需要通过Looper.loop()从MessageQueue中获取Message,BlockCanary就是通过计算事件分发的时间间隔来判断当前是否出现卡顿。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Looper.java
public void setMessageLogging(@Nullable Printer printer) {
mLogging = printer;
}

public static void loop() {
for (;;) {
//读取设置的 logging
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}

...
//事件分发
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
}
}

可以通过给Handler中的Looper对象设置setMessageLogging(),对事件的分发进行监听。

1
2
3
4
5
6
Looper.getMainLooper().setMessageLogging(new Printer(){
@Override
public void println(String x){
//x 包含了以下内容 Message.target Message.callback Message.what
}
})

5.View.post()和Handler.post()有什么区别?

Handler-View.post

1
2
3
4
5
6
7
8
9
10
11
12
//View.java
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}

// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().post(action);
return true;
}

需要判断attachInfo是否为null,不为null直接执行handler.post()去执行任务;否则,插入到getRunQueue()中。

现在需要分为两部分进行分析:

AttachInfo

1
2
3
4
5
6
//View.java
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
//在此处进行赋值
mAttachInfo = info;
...
}

这时需要知道何时调用了dispatchAttachedToWindow(),需要向上看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//ViewGroup.java
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
...
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
final View child = children[i];
child.dispatchAttachedToWindow(info,
combineVisibility(visibility, child.getVisibility()));
}
final int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
for (int i = 0; i < transientCount; ++i) {
View view = mTransientViews.get(i);
view.dispatchAttachedToWindow(info,
combineVisibility(visibility, view.getVisibility()));
}
}

再往上就是DecorViewDecorView继承自ViewGroup,所以最终就是到了ViewRootImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//ViewRootImpl.java
private void performTraversals() {
//mView 此处指的是 DecorView
final View host = mView;
...
if (mFirst) {
mFullRedrawNeeded = true;
mLayoutRequested = true;
...
host.dispatchAttachedToWindow(mAttachInfo, 0);
}
...
//绘制流程
performMeasure()

performLayout()

performDtraw()
}

是从ViewRootImpl.performTraversal()向下执行到DecorView.dispatchAttachedToWindow()最后执行到View.dispatchAttachedToWindow()

1
2
3
4
5
6
7
8
9
10
11
public ViewRootImpl(Context context, Display display) {
...
mFirst = true; // true for the first time the view is added
mAdded = false;
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
context);
...

}

final ViewRootHandler mHandler = new ViewRootHandler();

是在ViewRootImpl初始化的时候构建了AttachInfo对象,其中attachInfo.handler指的就是ViewRootHandler

所以最后通过View.post()执行的任务都会切换到ViewRootHandler上去执行。

HandlerActionQueue

mAttachInfo未赋值时(尚未执行 dispatchAttachedToWindow()),缓存当前无法执行的Runnable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//HandlerActionQueue.java
public class HandlerActionQueue {
private HandlerAction[] mActions;

//缓存任务
public void post(Runnable action) {
postDelayed(action, 0);
}

public void postDelayed(Runnable action, long delayMillis) {
final HandlerAction handlerAction = new HandlerAction(action, delayMillis);

synchronized (this) {
if (mActions == null) {
mActions = new HandlerAction[4];
}
mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
mCount++;
}
}

//执行缓存的任务
public void executeActions(Handler handler) {
synchronized (this) {
final HandlerAction[] actions = mActions;
for (int i = 0, count = mCount; i < count; i++) {
final HandlerAction handlerAction = actions[i];
handler.postDelayed(handlerAction.action, handlerAction.delay);
}

mActions = null;
mCount = 0;
}
}

//缓存runnable和执行时间
private static class HandlerAction {
final Runnable action;
final long delay;

public HandlerAction(Runnable action, long delay) {
this.action = action;
this.delay = delay;
}

public boolean matches(Runnable otherAction) {
return otherAction == null && action == null
|| action != null && action.equals(otherAction);
}
}
}

mAttachInfo尚未赋值时,就会缓存View.post()要执行的任务

1
2
3
4
5
6
7
8
9
10
//View.java
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
mAttachInfo = info;
...
if (mRunQueue != null) {
mRunQueue.executeActions(info.mHandler);
mRunQueue = null;
}
...
}

dispatchAttachedToWindow()执行了关键的两步:

  1. 赋值mAttachInfo
  2. 执行View.post()未执行的任务

总结

View.post()内部自动分为两种情况:

  • 尚未执行dispatchAttachedToWindow():尚未赋值mAttachInfo,将需要执行的任务缓存到HandlerActionQueue,等待dispatchAttachedToWindow()之后通过ViewRootHandler`执行。
  • 已执行dispatchAttachedToWindow():已赋值mAttachInfo,直接调用ViewRootHandler执行对应任务即可。

ViewRootHandler绑定的Looper为MainLooper,所以通过View.post()的操作都会在主线程执行。

dispatchAttachedToWindow()是在ViewRoootImpl.performTraversals()中执行的。

为什么可以获取宽高

前面有讲过在onCreate()调用View.post()可以获取View的宽和高,下面简单的分析原因。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//ViewRootImpl.java
private void performTraversals() {
...
host.dispatchAttachedToWindow(mAttachInfo, 0);
...
// 绘制流程
}

void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
...
performTraversals();

}
}

final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}

final TraversalRunnable mTraversalRunnable = new TraversalRunnable();

void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
//交给Chreographer在收到Vsync信号去执行 mTraversalRunnable 也就是 performTraversals()
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
...
}
}

这边转到Choreographer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//Choreographer.java
public static Choreographer getInstance() {
return sThreadInstance.get();
}

private static final ThreadLocal<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
@Override
protected Choreographer initialValue() {
Looper looper = Looper.myLooper();//此时looper对应的是MainLooper
if (looper == null) {
throw new IllegalStateException("The current thread must have a looper!");
}
Choreographer choreographer = new Choreographer(looper, VSYNC_SOURCE_APP);
if (looper == Looper.getMainLooper()) {
mMainInstance = choreographer;
}
return choreographer;
}
};

private Choreographer(Looper looper, int vsyncSource) {
mLooper = looper;
mHandler = new FrameHandler(looper);//由MainLooper构建的Handler
...
}

private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis)
{
if (DEBUG_FRAMES) {
Log.d(TAG, "PostCallback: type=" + callbackType
+ ", action=" + action + ", token=" + token
+ ", delayMillis=" + delayMillis);
}

synchronized (mLock) {
final long now = SystemClock.uptimeMillis();
final long dueTime = now + delayMillis;
mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);

if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);//设置异步消息 把TraversalRunnable置于消息里
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}

根据上述源码分析得到结论TraversalRunnable也会运行到FrameHandler上。

Handler的MessageQueue是按照顺序执行的,就需要等到performTraversals()执行完毕后,才可以执行后续的任务(HandlerActionQueue中缓存的任务。)。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!