前言
文章是记录自己研究源码的过程,方便日后的回顾,文章可能篇幅过长。
Handler 基本使用
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
mTextView.setText((String) msg.obj);
return false;
}
});
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message message = Message.obtain();
message.obj = "Handler Message";
handler.sendMessage(message);
}
}).start();
源码分析
Handler -> sendMessage
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
Handler -> sendMessageDelayed
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
Handler -> sendMessageAtTime
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);
}
Handler -> enqueueMessage
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);
}
这里将 Handler 赋值给 msg.target
queue.enqueueMessage() -> MessageQueue.enqueueMessage()
MessageQueue -> enqueueMessage
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.");
}
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) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
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;
}
修改一下代码
Message message1 = Message.obtain();
message1.obj = "Handler Message1";
handler.sendMessage(message1);
Message message2 = Message.obtain();
message2.obj = "Handler Message2";
handler.sendMessageDelayed(message2, 1000);
Message message3 = Message.obtain();
message3.obj = "Handler Message3";
handler.sendMessageDelayed(message3, 500);
发送 3 条消息,然后来分析 enqueueMessage 里的代码
MessageQueue -> enqueueMessage ( message1 )
boolean enqueueMessage(Message msg, long when) {
...
msg.when = when;//注释 1
Message p = mMessages;//注释 2
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;//注释 3
mMessages = msg;//注释 4
needWake = mBlocked;
} else {
...
}
...
}
当发送 message1 消息时,mMessages 是还没有赋值的,所以会执行 if 内的代码片段
注释 1 : message1.when = 0
注释 2 : Message p = null
注释 3 : message1.next = null
注释 4 : mMessages = message1
MessageQueue -> enqueueMessage ( message2 )
boolean enqueueMessage(Message msg, long when) {
...
msg.when = when;//注释 1
Message p = mMessages;//注释 2
if (p == null || when == 0 || when < p.when) {
...
} else {
...
Message prev;
for (;;) {
prev = p;//注释 3
p = p.next;//注释 4
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next //注释 5
prev.next = msg;//注释 6
}
...
}
注释 1 : message2.when = 1000
注释 2 : Message p = message1
注释 3 : prev = message1
注释 4 : message1 = null
注释 5 : message2.next = message1
注释 6 : message1.next = message2
MessageQueue -> enqueueMessage ( message3 )
boolean enqueueMessage(Message msg, long when) {
...
msg.when = when;//注释 1
Message p = mMessages;//注释 2
if (p == null || when == 0 || when < p.when) {
...
} else {
...
Message prev;
for (;;) {
prev = p;//注释 3
p = p.next;//注释 4
if (p == null || when < p.when) {//注释5
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next //注释 6
prev.next = msg;//注释 7
}
...
}
注释 1 : message3.when = 500
注释 2 : Message p = message1
注释 3 : prev = message1
注释 4 : message1 = message2
注释 5 : 500 < 1000 跳出循环
注释 6 : message3.next = message2
注释 7 : message1.next = message3
所以可以得出一个结论
- Message 是一个链表
- Message 中通过 when 时间大小进行排序
所以 handler.sendMessage 方法的作用是将消息加入到队列中。
那么是在哪个位置处理消息呢?这里先带着疑问,先思考下面的问题。
new Thread(new Runnable() {
@Override
public void run() {
Handler handler1 = new Handler();
}
}).start();
java.lang.RuntimeException: Can't create handler inside thread Thread[Thread-3,5,main] that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:207)
at android.os.Handler.<init>(Handler.java:119)
at com.giraffe.school.MainActivity$2.run(MainActivity.java:47)
at java.lang.Thread.run(Thread.java:919)
为什么在子线程中实例化 Handler 会报错 ?跟着 Handler 源码看看
public class Handler {
...
public Handler() {
this(null, false);
}
public Handler(@Nullable Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
...
}
根据代码可以判断出 mLooper 是为 null 的,所以会抛出错误。
Looper -> myLooper
public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
...
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
...
}
sThreadLocal -> get
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
get 方法的作用是通过 currentThread 获取一个 ThreadLocalMap 对象,然后以 sThreadLocal 为键来获取 Looper。
为什么在主线程中实例 Handler 不会报错 ?跟着 ActivityThread 源码
ActivityThread -> main
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
}
Looper -> prepareMainLooper
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
Looper -> prepare
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));
}
ThreadLocal -> set
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
prepare作用set 方法的作用是通过 currentThread 获取一个 ThreadLocalMap 对象,然后将当前的 sThreadLocal 作为键,Looper 作为值存储起来,所以一个线程有且只有一个 Looper。
因为 ActivityThread 在 main 方法中已经调用了 prepare 方法,ThreadLocalMap 会设置一个(ThreadLocal,Looper) 的值,我们在 Activity 主线程中使用 Handler,通过当前主线程拿到 Looper,所以在主线程中使用 Handler 不会报错。
子线程没有调用 prepare 方法,所以 ThreadLocalMap 会拿到一个 null 值,这就是导致抛出异常的原因。所以在子线程中使用 Handler 时,需要手动调用 Looper.prepare() 方法。
ActivityThread -> main
public static void main(String[] args) {
...
Looper.loop();
...
}
Looper -> loop
public static void loop() {
final Looper me = myLooper();
...
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next();
...
msg.target.dispatchMessage(msg);
...
}
...
}
loop 方法是获取当前线程的 Looper 对象,通过 Looper 对象获取到 MessageQueue,循环便利 Message,然后通过 Handler.dispatchMessage() 方法发送消息
Handler -> dispatchMessage
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
在分发消息时,会根据 msg.callback 来处理不同的方法。如果 msg.callback 不为 null,则调用 handleCallback() 方法。如果 msg.callback 为 null,则调用
handleMessage() 方法。
msg.callback 是什么?来到 Message 类中看看
public final class Message implements Parcelable {
...
@UnsupportedAppUsage
/*package*/ Runnable callback;
public static Message obtain(Handler h, Runnable callback) {
Message m = obtain();
m.target = h;
m.callback = callback;
return m;
}
@UnsupportedAppUsage
public Message setCallback(Runnable r) {
callback = r;
return this;
}
...
}
callback 是一个 Runnable,callback 赋值的地方有两个,一个是 obtain,一个是 setCallback
Handler -> handleCallback
private static void handleCallback(Message message) {
message.callback.run();
}
Handler -> handleMessage
public void handleMessage(@NonNull Message msg) {
}
所以如果设置了 Runnable ,那么会通过 handleCallback 调用 Runnable 的 run 方法。
如果没有设置 Runnable,那么会调用 handleMessage 方法,让我们自己去处理。
Handler 大致流程图
Handler流程解析总结
- ActivityThread main 方法会调用 Loop.prepare() 方法,ThreadLocal 会设置一个 (mainThread,Looper) 的 ThreadLocalMap
- ActivityThread main 方法会调用 Loop.loop() 方法,Loop 会循环便利 MessageQueue,当 MessageQueue 不为空会通过 Handler.dispatchMessage 分发消息
- Handler.sendMessage 会将当前 Handler 绑定到 Message.target,并且将 Message 加入到 MessageQueue 中
- 这时候 MessageQueue 不为空,Loop 会通知 Handler.dispatchMessage。如果设置了 Runnable ,那么会通过 handleCallback 调用 Runnable 的 run 方法。
如果没有设置 Runnable,那么会调用 handleMessage 方法,让我们自己去处理
网友评论