handler源码分析
1.基本使用
handler:发送和接受消息
looper:用于轮询消息队列
MessageQueue:消息队列用于存储消息和管理消息
kotlin
//UI线程
val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when (msg.obj) {
CODE_UPDATE -> {
//处理消息
}
}
}
}
Thread {
val message = Message.obtain()
message.what = CODE_UPDATE
//发送消息
handler.sendMessage(message)
//发送一条延时消息
handler.sendMessageDelayed(message,200)
}.start()
Thread{
handler.post {
// 在UI线程执行的任务
}
}
1.创建handler对象
2.使用post方法或者sendMessage方法
3.在handler所在的线程,进行消息处理
两种发送信息的方式,一种是发送Message,一种是post。
分别看下两种方式的源码处理
2.流程解析
2.1 handler创建
less
//android.os.Handler
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;
}
class Handler{
final Looper mLooper;
final MessageQueue mQueue;
...
}
可以看到,在handler创建的时候,需要传入一个looper,而mQueue被Looper所持有
2.2 looper创建
在ActivityThread中的main方法中,已经为我们创建了looper
arduino
android.app.ActivityThread
public static void main(String[] args) {
... 省略代码
//初始化looper和MessageQueue
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
}
... 省略代码
//轮询
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
Looper.prepareMainLooper()进行了Looper和MessageQueue的创建
csharp
android.os.Looper
public static void prepareMainLooper() {
//不可退出
prepare(false);
synchronized (Looper.class) {
//如果looper已经存在,则抛出异常
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
从代码可以看出,主要是通过Looper.prepare方法进行创建looper,先调用sThreadLocal.get()获取Looper,如果Looper已经存在,则抛出异常。如果不存在,则创建Looper并且设置到ThreadLocal中。再来看看ThreadLocal的具体实现
swift
android.os.Looper
public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
}
ini
java.lang.ThreadLocal
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null){
map.set(this, value);
}else{
createMap(t, value);
}
}
ThreadLocal的作用是为每个线程提供一个独立的变量副本,通过ThreadLocalMap来实现对每个线程的变量副本的存储和获取。获取到当前线程对应的ThreadLocalMap,static final修饰的threadLocal变量作为key,value则是looper实例,进行存储。由于key永远是同一个,再加Looper.prepare会先判断当前线程是否存在looper,所以Looper在每个线程中只会存在一个Looper
2.3 MessageQueue创建
ini
android.os.Looper
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
在looper的构造函数中,创建了MessageQueue,这个时候handler和looper,messagequeue就绑定在一起了。
2.4 handler.sendMessage
less
android.os.Handler
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
//post 将runnable设置为msg的callback
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
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);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
通过上面的代码可以看出,无论是sendMessage还是post都会走到sendMessageDelayed,在走到sendMessageAtTime方法,uptimeMillis则是一个具体的时间点,最后走到了enqueueMessage方法,msg.target = this,指向了当前handler。最后由queue.enqueueMessage进行处理。在一开始创建handler的时候,已经看到了mQueue是MessageQueue。接下来看MessageQueue是怎么处理这个消息的
ini
android.os.MessageQueue
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
//加锁
synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
//Looper.myLooper().quit(); 应用退出的时候才会被标记为true
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;
if (p == null || when == 0 || when < p.when) {
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;
}
}
//唤醒
if (needWake) {
nativeWake(mPtr);
}
return true;
}
插入队列这里进行了加锁,保证了线程安全。从代码看出这个队列是优先级队列,按照msg的when进行排序。当头节点为null或者头节点的when大于msg的when时,msg作为头节点。如果msg的when大于头节点,轮询将msg插入到合适的位置。
2.5 Looper.loop
已经将msg插入到messagequeue中,接下来看看loop是怎么处理的。
java
android.os.Looper
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.");
}
for (;;) {
if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
}
}
}
private static boolean loopOnce(final Looper me,final long ident, final int thresholdOverride) {
//取出队列中的消息
Message msg = me.mQueue.next(); // might block
if (msg == null) {
return false;
}
...省略代码
//msg.target就是handler
msg.target.dispatchMessage(msg);
...省略代码
msg.recycleUnchecked();
return true;
}
ini
android.os.MessageQueue
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
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) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
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) {
// No idle handlers to run. Loop and wait some more.
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;
}
}
在循环中,程序不断地从消息队列中获取消息。如果成功获取到消息,程序会判断当前时间是否小于消息的触发时间(msg.when)。如果是,会计算出下一次轮询超时的时间(nextPollTimeoutMillis),然后通过调用nativePollOnce方法来进行等待,该方法底层会调用Linux的epoll方法。
如果当前消息队列中没有任何消息,程序将会无限等待,直到有新的消息到达。这个过程会不断重复,保证程序能够及时处理消息
msg.target是handler,在取出msg后,最终会调用到handler的dispatchMessage方法。接下来又会执行msg.recycleUnchecked()方法。
ini
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
这里将msg的标记进行置空,释放所有资源,在判断当前队列的msg数量是否小于MAX_POOL_SIZE(50),如果小于则插入到表头。
2.6 Handler.dispatchMessage
typescript
public void dispatchMessage(@NonNull Message msg) {
//post runnable设置msg的callback
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
如果是post过来的消息,一开始传入的时候已经将runnable设为msg的callback,这个时候直接执行run函数,否则由handler的callback回调处理。