Android_Handler源码分析
本文由 Luzhuo 编写,转发请保留该信息.
原文: http://blog.csdn.net/Rozol/article/details/72826128
- handler可以让耗时操作在辅助线程进行,处理完发送消息,让ui更新在主线程进行
- 关键词: handler [ˈhændlɚ] / message [ˈmɛsɪdʒ] / runnable [‘rʌnəbəl] / looper [‘lu:pə] / message queue [kju] (注:很多程序员Queue的发音不标准)
项目使用(用于实际开发中的代码)
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int MESSAGE = 0x0001;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MESSAGE:
Log.e(TAG, "what:" + msg.what); // what:1
Log.e(TAG, "obj:" + msg.obj); // obj:sendEmptyMessage(what)
break;
default:
super.handleMessage(msg);
}
}
};
public void sendMessage(View v) {
new Thread() {
@Override
public void run() {
Message msg = Message.obtain();
msg.what = 1;
msg.obj = "sendEmptyMessage(what)";
// 多种handler发送方式
// handler.sendEmptyMessage(1);
handler.sendMessage(msg);
// handler.postDelayed(new Runnable() {
// @Override
// public void run() { }
// }, 5 * 1000);
super.run();
}
}.start();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onDestroy() {
handler.removeCallbacksAndMessages(null);
handler = null;
super.onDestroy();
}
}
基本使用(用于讲解)
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
- handler在主线程创建
public void sendMessage(View v) {
new Thread() {
@Override
public void run() {
Message msg = Message.obtain();
msg.what = 1;
msg.obj = "sendEmptyMessage(what)";
handler.sendMessage(msg);
super.run();
}
}.start();
}
- 子线程处理完耗时操作,通过handler发送Message / Runnable, 通知更新handler更新ui
- handler.post(runnable) 底层源码调用与handler.sendMessage(message)相同,都是调用handler.sendMessageAtTime(message)
源码分析
1.先看下new Handler()的源码
public class Handler {
public Handler(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 that has not called Looper.prepare()");
}
// ↓↓↓
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
}
Handler会调用 Looper.myLooper() 去获取Looper
public final class Looper { public static @Nullable Looper myLooper() { return sThreadLocal.get(); } }
- Looper是调用 sThreadLocal.get() 获取的
- 如果 sThreadLocal.get() 没有获取到对应的该线程的Looper, 则会抛 RuntimeException; 如果有获取到对应的Looper, 则执行 mQueue = mLooper.mQueue 获取 MessageQueue
那么什么时候是有Looper, 什么时候又是没有的呢?
- 在主线程创建 Handler 不会抛该异常 (基本使用的案例代码,handler就是在主线程创建的)
在子线程创建的 Handler 就抛了该异常
new Thread(new Runnable() { @Override public void run() { Looper.prepare(); // <= handler = new Handler() { @Override public void handleMessage(Message msg) { } }; Looper.loop(); // <= } }).start();
- 当我们在子线程中创建 Handler 之前调用 Looper.prepare() 就不会抛该异常了
我们猜想可能是调用 Looper.prepare() 给 ThreadLocal 设置Looper
public final class Looper { public static void prepare() { prepare(true); } 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 设置了一个新的 Looper()
我们在看看 new Looper(quitAllowed) 时做了什么
public final class Looper { private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } }
- 可以看出 MessageQueue 是由 Looper创建的
我们再调用 Looper.loop(), Handler才能收到消息, 我们来看看他到底做了什么?
public final class Looper { 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; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); // ↓↓↓ for (;;) { // ↓↓↓ Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long traceTag = me.mTraceTag; if (traceTag != 0) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } try { // ↓↓↓ msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); } } }
- 调用 Looper me = myLooper() 获取Looper
- 调用 MessageQueue queue = me.mQueue 获取MessageQueue
- 可以看出 MessageQueue是在Looper对象中的, 这可以说明一个每个 Looper 都包含一个 MessageQueue
- for (;;) 可以看出Looper做了永生循环
- 调用 Message msg = queue.next(), 从 MessageQueue 中取出Message
- 调用了 msg.target.dispatchMessage(msg), 那么 msg.target 是什么呢? 先留着
最后调用了 msg.recycleUnchecked()
public final class Message implements Parcelable { 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 = -1; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } } }
- 可以看出 msg.recycleUnchecked() 只是对 Message 做了初始化,并返回了池子里
2.在看下 Message msg = Message.obtain(); 的源码
public final class Message implements Parcelable {
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
}
- 很简单, 就是从池子里去取 Message, 如果池子里没有就 new Message()
3.再来看看 handler.sendMessage(msg) 的源码
public class Handler {
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
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) {
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) {
// ↓↓↓
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
// ↓↓↓
return queue.enqueueMessage(msg, uptimeMillis);
}
}
- 现在 msg.target 是什么的问题解决了,原来他是 Handler, msg.target.dispatchMessage(msg) 是什么意思?待会儿继续看源码, 现在暂时先跳过
最后调用了 queue.enqueueMessage(msg, uptimeMillis)
public final class MessageQueue { 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"); 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 根据 when时间值 插入到队列中
4.最后看看一个遗留的问题, msg.target.dispatchMessage(msg) 是什么意思? 通过3的分析我们已经知道 msg.target 是Handler对象
public class Handler {
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
public void handleMessage(Message msg) {
}
}
- 原来是回调 handleMessage 的意思啊
5.简单的总结下,顺便画个图捋一捋
- 创建Handler前,(先调用 Looper.prepare() [prɪˈper], 创建Looper(同时Looper会创建MessageQueue)), 再创建 Handler, (然后调用 Looper.loop(), 让Looper的永生循环执行起来)
- Handler 通过 handler.sendMessage(msg), 将自己放入 Message 中,然后将 Message 放入 Looper 的 MessageQueue 队列中
- Looper 不断的从 MessageQueue 中取出 Message, Message 里的 Handler 调用回调方法.
handler引发的内存泄露问题
Q. (基本使用的代码)使用内部类创建 Handler, 该Handler隐式持有Activity的引用,可以调用Activity的属性和方法;如果Handler发送的延迟Message等待时间过长,而此时Activity正在被回收时, 由于Message持有Handler的引用,而Handler持有Activity的引用,导致该Activity无法被回收,从而导致内存泄露问题.
A. 解决方案:(完整代码见项目使用)
- Activity销毁时,清空该Handler相关的所有Message, 并将Handler指向null.