一直对Handler的工作原理非常好奇,看了网上很多帖子还是感觉似懂非懂。今天专门亲自从源码角度分析一下Handler的工作过程。
private Handler mHandler;
@Override
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.tv01);
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
这是很常规的一种写法,实际上这样写是不对的,这样的话Handler的会持有Activity的引用,导致Activity不能及时得到回收。并且从源码中可以看到
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 followingHandler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
Handler在构造的时候会检查你是否将它声明为单独的一个类,如果没有单独去静态继承Handler类去实现的话发出警告,因为这个问题不是致命的。
正确的方式是这样做,
private static class MyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
}
接下来会发生这个
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't createhandler inside thread that has not called Looper.prepare()");
}
Looper.myLooper()去拿当前线程的Looper对象。如果是在主线程中Looper.prepare()方法在创建Activity之前已经执行,所以myLooper()会返回一个Looper对象。但是如果是在子线程去调myLooper()是没法拿到Looper对象的。看看Looper::prepare()的源码,
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Loopermay be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
Looper::prepare()方法向ThreadLocal变量中保存了一个Looper对象。
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
而Looper::myLooper()就是将ThreadLocal变量中保存的值返回出去。接下来这句
mQueue = mLooper.mQueue;
Handler用的Queue是Looper的Queue。
Handler中的发送消息最终都会调到这个方法
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);
}
而这个方法返回时执行了Handler::enqueueMessage方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
该方法再返回时又调用了MessageQueue::enqueueMessage方法。此时我们应该去到MessageQueue类中查看源码,
boolean enqueueMessage(Message msg, long when) {
......
if (p == null || when == 0 || when < p.when) {
// New head, wake up theevent queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within themiddle of the queue. Usually we don'thave to wake
// up the event queue unlessthere is a barrier at the head of the queue
// and the message is theearliest 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;
}
......
}
return true;
}
这个就是将发送来的消息保存到消息队列等待调度。之后的事情就交给Looper来做了。
public static void loop() {
......
final MessageQueue queue =me.mQueue;
// Make sure the identityof this thread is that of the local process,
// and keep track of what thatidentity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicatesthat the message queue is quitting.
return;
}
// This must be in a localvariable, in case a UI event sets the logger
Printer logging =me.mLogging;
if (logging != null) {
logging.println(">>>>>Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
......
}
}
当Looper::loop()方法被调用以后队列就活起来了,不断地获取消息并分发消息。最后就是Handler的回调了
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
之后就回到了最开始我们提到的关于如何实例化一个Handler对象,之后覆写里面的Handler::handleMessage(msg)方法。整个消息循环就跑起来了。
这里最大的一个问题在于Looper::loop()中的死循环是如何跑起来的,为什么没有开启新线程执行Looper::loop(),但是也没有阻塞主线程?这个可能与Binder机制有关,待进一步研究。