Handler 是用来做什么的?
总的来说,Handler可以跨线程发送Message
对应用层来说,Android不允许主线程以外的线程更新UI,所以需要借助Handler来更新UI
对Framework来说,AMS通过Binder跨进程,发送消息到ApplicationThread,ApplicationThread
向H
(继承自Handler)发送消息,H收到消息后再ActivityThread中处理
Handler Looper MessageQueue Message 四者关系?
一次完整的Handler使用流程是怎么样的?
一、Looper.prepare( ):
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//设置Looper到ThreadLocal
sThreadLocal.set(new Looper(quitAllowed));
}
二、在消费线程实例化Handler,Handler在ThreadLocal中放置属于此线程的Looper。设置将来获得Message的方法(复写dispatchMessage()
方法,或者通过接口回调)
Handler 所有的构造方法:
Handler获得Looper有两种途径:
- 构造方法
-
Looper.myLooper()
的静态方法
public Handler(Callback callback, boolean async) {
//Looper从ThreadLocal获得该线程的mLooper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//获得该线程的MessageQueue
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
三、在另一个线程,用Handler的引用,发送Message
//最终会调用该方法
public boolean sendMessageAtTime(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(MessageQueue queue, Message msg, long uptimeMillis) {
//在Message中保存该Handler的引用
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//插入一条消息到单链表MessageQueue
return queue.enqueueMessage(msg, uptimeMillis);
}
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
//重复生产了多条相同的Message而没有被消费掉
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//已经没有Looper啦,插不进去了
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
//标记正在使用
msg.markInUse();
msg.when = when;
//哨兵
Message p = mMessages;
boolean needWake;
//此次传入的msg为头
if (p == null || when == 0 || when < p.when) {
//设置哨兵
msg.next = p;
//mMessage更新为该msg
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
//prev为msg的前一个
Message prev;
for (;;) {
//既然p不为空,p即使msg的前一个
prev = p;
//更新p为p的下一个
p = p.next;
//p的下一个为空,意味着到达尾部,跳出
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
//msg的下一个为p,p为空
msg.next = p;
//插入到末尾
prev.next = msg;
}
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
四、Looper.loop()
public static void loop() {
//获得属于该线程的Looper
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获得MessageQueue
final MessageQueue queue = me.mQueue;
for (;;) {
//循环去获取下一条消息
Message msg = queue.next();
//queue.next()返回null <==> 该线程的looper退出了
if (msg == null) {
return;
}
try {
//msg.target返回Handler,Handler.dispatchMessage(msg)完成消息的传递
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
}
}
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1;
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//没有消息的话线程进入休眠
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
nextPollTimeoutMillis = -1;
}
if (mQuitting) {
dispose();
return null;
}
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);
}
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 {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
pendingIdleHandlerCount = 0;
nextPollTimeoutMillis = 0;
}
}
Looper到底保存在哪里的?
一个线程一般私有三种类型的数据:
- 栈
- Thread Local Storage
- 寄存器
在一个线程调用Looper.prepare()
后,会实例化一个Looper对象,保存在Thread Local Storage中。 Handler可以从TLS中获得Looper的引用,这样就可以把Thread和Looper形成一一对应的关系
Handler如何循环?
调用Looper.loop( )后,会进入一个永真循环,去调用queue.next( )
而queue.next( )又是一个永真循环,不断查询是否有新的消息
循环在什么时候退出?
对于Looper.loop()
中的循环,当且仅当queue.next()
返回null时退出
对于queue.next()
中的循环,当且仅当mQuitting为真时退出
queue.next()
什么时候会返回null呢?
查看源码我们发现有两处return null
if (ptr == 0) {
return null;
}
if (mQuitting) {
dispose();
return null;
}
对于第一处:
当一个线程的Looper已经退出,并且所有的消息都处理了,如果再重启这个Looper,就会使得ptr==0
为真
意思就是一个线程处理了所有事件,手动退出Looper。以后就算再重新调用Looper.loop()
,也是不能正常收到事件的
对于第二处:
当mQuitting为真会进入该段代码
那什么情况下mQuitting会为真呢
在Looper.quit( ):
public void quit() {
mQueue.quit(false);
}
MessageQueue.quit():
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
可以发现,当且仅当我们调用了MessageQueue.quit()
,mQuitting
为真,MessageQueue.next()
返回null,跳出循环,进而调到next()
方法的Looper.loop()
方法也跳出循环
也就是说,只有我们调用了Looper.quit()后,循环才会停止
同时我们注意到了throw new IllegalStateException("Main thread not allowed to quit.");
这个异常,也就是说我们不可能主动退出主线程的Looper,不能手动停止主线程的消息循环
主线程的Handler在哪实例化的?Looper又在哪里调用prepare( )和loop( )的?
在ActivityThread中有以下代码
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
//准备主线程的Looper
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
//创建ApplicationThread,即开启Binder,接收AMS消息
thread.attach(false);
//实例化Handler,此Handler接收ApplicationThread的消息
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//Looper.loop( )
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
可以看见我们调用Looper.prepareMainLooper()
来准备我们主线程的Looper
该方法会检查主线程的Looper是否已经创建过了,如果创建过了,就抛出异常
并且设置主线程的Looper是不允许退出的,而且,只有主线程的Looper能够有此殊荣
主线程的Handler类名叫H,是ActivityThread类的内部类
handleMessage(Message msg)
方法负责分发事件,这个方法在ApplicationThread
被sendMessage()
方法调用,ApplicationThread
继承自Binder
,接收来自AMS的IPC消息