从Handler说起
常规的Handler使用过程如下所示,运行如下代码应该就能弹出Toast了
public class MainActivity extends AppCompatActivity {
private static MyHandler handler = new MyHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(){
@Override
public void run() {
super.run();
//耗时任务 ...
handler.sendEmptyMessage(0);
}
}.start();
}
public class MyHandler extends Handler{
private WeakReference<Activity> mActivity;
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case 0:
if(mActivity.get() != null){
Toast.makeText(mActivity.get(),"收到消息",Toast.LENGTH_LONG).show();
}
break;
}
}
MyHandler(Activity activity){
mActivity = new WeakReference<>(activity);
}
}
}
那么为什么在子线程通过handler.sendMessgae(),主线程就会去执行handler里面的handleMessage(),先来看看Handler的创建过程吧
//Handler.java
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
该方法里判断了当前线程是否含有Looper如果不存在则抛出RuntimeException,由于上文中的Handler是在主线程中进行创建的而在ActivityThread会调用Looper.prepareMainLooper()创建主线程的Looper因此主线程的Looper != null (主线程创建Looper的过程这里有讲),然后来看看Looper.myLooper()
//Looper.java
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
sThreadLocal是静态变量用来保存每个线程的Looper对象的,在每个线程调用sThreadLocal.get()都获取的是当前线程Looper,既然有get那么是什么时候set进去的呢?来看看Looper.prepareMainLooper()
//Looper.java
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
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));
}
该方法里面创建了Looper对象并将其设置到sThreadLocal里面,下面来看Looper的构造方法
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
里面又创建了MessageQuene实例,下面来看看子线程调用handler.sendEmptyMessage(0)系统都做了哪些东西
//Handler.java
public final boolean sendEmptyMessage(int what) {
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();//1
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) { //2
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; //3
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when; //4
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) { //5
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else { //6
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;
}
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
至此消息就已经保存到了Handler所对应的Looper的MessageQuene里面,Message以单链表形式存储,其中MessageQuene里面的成员变量mMessage保存的是单链表的链首,上述代码有几个需要注意
- Message池中获取一个message,自己用的时候也不要new,也使用Message.obtain()
- 正常情况下基本不可能为空,应该Handler不为空Looper就不为空那么MessageQuene也不为空
- 设置Message.target = Handler 保存Handler引用到时候取出消息的时候要用到
- 设置Message执行的时间
- 如果单链表为空则直接把该Message赋值给MessageQuene里面的mMessage这个链首对象
- 若不为空则根据Message的时间先后找到合适的位置进行插入
由于主线程在ActivityThread.main()中会调用Looper.loop()进行死循环不断从MessageQuene里面取出消息,来看看Looper.loop()
//Looper.java
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue; //1
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) { //2
Message msg = queue.next(); // 3
if (msg == null) { //4
// No message indicates that the message queue is quitting.
return;
}
...
try {
msg.target.dispatchMessage(msg); //5
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
}
}
从上可知该方法是一个死循环,唯一能退出该循环的条件是msg == null
- 获取该线程所对应的Looper中的MessageQuene实例
- 死循环一直等待消息
- 调用MessageQuene.next()尝试从消息队列中取出消息
- 如果msg == null则退出循环一般只有当外界调用Looper.quit()后才会返回null
- 调用Handler.dispatchMessage()
先来看看第3点
//MessageQuene.java
Message next() {
for (;;) {
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 {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
return msg;
}
} else {
nextPollTimeoutMillis = -1;
}
if (mQuitting) { //1
dispose();
return null;
}
}
}
}
该方法主要内容就是根据mMessager这个单链表链首取出当前时刻已经ready的第一个Message,从注释1处可以得知只有当调用了MessageQuene.quit该方法才会返回null,而Looper.quit()内部调用了MessageQuene.quit(),当Looper取出消息调用Message.target.dispatchMessage(msg),而上文已经讲了当Message插入当单链表中会把Handler设置成Message.target,因此来看看Handler.dispatchMessage(msg)
//Handler.java
public void dispatchMessage(Message msg) {
if (msg.callback != null) { //1
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {//2
return;
}
}
handleMessage(msg);//3
}
}
该方法很简单,就是分派了下消息
- 如果Message的Callback不为空则直接执行该Message的Callback
- 如果Handler的mCallback不为空(该成员变量在构造方法中赋值)则执行该Callback并根据返回值判断是否执行Handler.handlerMessage()
- 当Message.callback为空并且Handler的callback也为空或者不为空但是返回为false,才会执行Handler.handleMessage()