Android源码——Handler机制(一)
- Handler机制概述
- 介绍
- Handler机制模型
- Handler机制架构
- Handler机制源码解析
- ActivityThread
- Looper
- Handler
Handler机制概述
介绍
Handler是Android消息机制的上层接口。Handler可以将一个任务切换到Handler所在的线程中去执行。通常情况下,Handler的使用场景就是更新UI。
如下就是使用消息机制的一个简单实例:
public class BasicActivity extends AppCompatActivity {private static final String TAG = "BasicActivity";private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);Log.i(TAG, msg.what);}};@Overridepublic void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {super.onCreate(savedInstanceState, persistentState);setContentView(R.layout.activity_main);new Thread(new Runnable() {@Overridepublic void run() {// 耗时操作.....Message message = Message.obtain();message.what = 1;mHandler.sendMessage(message);}}).start();}
}
在子线程中,进行耗时操作,执行完操作后,发送消息,通知主线程更新UI。这便是消息机制的典型应用场景。我们通常只会接触到Handler和Message来完成消息机制,其实内部还有两大助手来共同完成消息传递。
Handler机制模型
消息机制主要包含:MessageQueue
,Handler
和Looper
这三大部分,以及Message
。
- Message: 需要传递的消息,可以传递数据;
- MessageQueue: 消息队列,但是它的内部实现并不是用的队列,实际上是通过一个单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。主要功能向消息池投递消息
MessageQueue.enqueueMessage
和取走消息池的消息MessageQueue.next
; - Handler: 消息辅助类,主要功能向消息池发送各种消息事件
Handler.sendMessage
和处理相应消息事件Handler.handleMessage
; - Looper: 不断循环执行
Looper.loop
,从MessageQueue
中读取消息,按分发机制将消息分发给目标处理者。
Handler机制架构
运行流程:在子线程执行完耗时操作,当Handler
发送Message
时,会调用MessageQueue.enqueueMessage
,向消息队列中添加Message
。当通过Looper.loop
开启循环后,会不断从线程池中读取消息,即调用MessageQueue.next
,然后调用目标Handler
(即发送该消息的Handler)的dispatchMessage
方法传递消息,然后返回到Handler
所在线程,目标Handler
收到消息,调用handleMessage
方法,接收处理消息。
每个线程只能存在一个Looper
,Looper
保存在ThreadLocal
线程中。主线程(UI线程)已经创建了一个Looper
,所以在主线程中不需要再创建Looper
,但是在其他线程中需要创建Looper
。每个线程可以有多个Handler
,即一个Looper
可以处理来自多个Handler
的消息。Looper
中维护一个MessageQueue
,来维护消息队列,消息队列中的Message
可以来自不同的Handler
。
Looper
有一个MessageQueue
消息队列,MessageQueue
有一组待处理的Message
,Message
中记录发送和处理消息的Handler
,Handler
中有Looper
和MessageQueue
。
Handler机制源码解析
ActivityThread
ActivityThread
类是用来启动Android
的,在main()
函数中准备相关环境,创建并启动Looper
循环。
主线程中不需要自己创建Looper
,这是由于在程序启动的时候,系统已经帮我们自动调用了Looper.prepare()
方法。
public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");// Install selective syscall interceptionAndroidOs.install();// CloseGuard defaults to true and can be quite spammy. We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);// Call per-process mainline module initialization.initializeMainlineModules();Process.setArgV0("<pre-initialized>");// 1. 把主线程和消息队列放进Looper中,同时把Looper放进ThreadLocal(每个线程绑定一个Looper)Looper.prepareMainLooper();// ....// 启动Looper循环,不断循环取出消息Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");
}
Looper
Looper
不断循环执行loop()
,从MessageQueue
中读取消息,按分发机制将消息分发给目标处理者。
- 初始化Looper
public final class Looper {// sThreadLocal.get() will return null unless you've called prepare().@UnsupportedAppUsagestatic final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();@UnsupportedAppUsageprivate static Looper sMainLooper; // guarded by Looper.class@UnsupportedAppUsagefinal MessageQueue mQueue;final Thread mThread;/** Initialize the current thread as a looper.* This gives you a chance to create handlers that then reference* this looper, before actually starting the loop. Be sure to call* {@link #loop()} after calling this method, and end it by calling* {@link #quit()}.*/public static void prepare() {prepare(true);}/*** 创建Looper,并保存在ThreadLocal,不能重复创建Looper,只能创建一个。 */private static void prepare(boolean quitAllowed) {// 不能重复创建否则报错if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per thread");}// 4. 实例化自己,封装mQueue和主线程,把自己放入ThreadLocal中sThreadLocal.set(new Looper(quitAllowed));}/*** Initialize the current thread as a looper, marking it as an* application's main looper. See also: {@link #prepare()}** @deprecated The main looper for your application is created by the Android environment,* so you should never need to call this function yourself.*/@Deprecatedpublic static void prepareMainLooper() {prepare(false);synchronized (Looper.class) {if (sMainLooper != null) {throw new IllegalStateException("The main Looper has already been prepared.");}sMainLooper = myLooper();}}/*** Return the Looper object associated with the current thread. Returns* null if the calling thread is not associated with a Looper.*/public static @Nullable Looper myLooper() {return sThreadLocal.get();}private Looper(boolean quitAllowed) {// 2. 实例化MessageQueuemQueue = new MessageQueue(quitAllowed);mThread = Thread.currentThread();}}
- 开启Looper
/*** 5. 调用Looper.loop()方法* Run the message queue in this thread. Be sure to call* {@link #quit()} to end the loop.*/public static void loop() {// 获取TLS存储的Looper对象final Looper me = myLooper();if (me == null) {throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");}if (me.mInLoop) {Slog.w(TAG, "Loop again would have the queued messages be executed"+ " before this one completed.");}me.mInLoop = true;// 获取Looper对象中的消息队列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();// 进入loop()主循环for (;;) {// 消息队列取出一条消息Message msg = queue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return;}// 默认为null,可通过setMessageLogging()方法来指定输出,用于debug功能// This must be in a local variable, in case a UI event sets the loggerfinal Printer logging = me.mLogging;if (logging != null) {logging.println(">>>>> Dispatching to " + msg.target + " " +msg.callback + ": " + msg.what);}// .....try {// 获取msg的目标Handler,然后用于分发Messagemsg.target.dispatchMessage(msg);// ....} catch (Exception exception) {// ...} finally {// ...}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();// 回收可能正在使用的消息msg.recycleUnchecked();}}
loop()
进入循环模式,不断重复下面的操作,直到消息为空时退出循环:读取MessageQueue
的下一条Message
;把Message
分发给相应的target
。
当next()
取出下一条消息时,队列中已经没有消息时,next()
会无限循环,产生阻塞。等待MessageQueue
中加入消息,然后重新唤醒。
Handler
消息辅助类,主要功能向消息池发送各种消息事件(Handler.sendMessage)和处理相应消息事件(Handler.handleMessage)。
- 创建Handler
public class Handler {@UnsupportedAppUsagefinal Looper mLooper;// 这里并没有实例化,指向Lopper的消息队列final MessageQueue mQueue;@UnsupportedAppUsagefinal Callback mCallback;final boolean mAsynchronous;@UnsupportedAppUsageIMessenger mMessenger;/*** Callback interface you can use when instantiating a Handler to avoid* having to implement your own subclass of Handler.*/public interface Callback {/*** @param msg A {@link android.os.Message Message} object* @return True if no further handling is desired*/boolean handleMessage(@NonNull Message msg);}/*** Subclasses must implement this to receive messages.*/public void handleMessage(@NonNull Message msg) {}}
构造函数:
@Deprecatedpublic Handler() {this(null, false);}@Deprecatedpublic Handler(@Nullable Callback callback) {this(callback, false);}@UnsupportedAppUsagepublic Handler(boolean async) {this(null, async);}/*** 第一种构造方法:给主线程调用,因为主线程已经调用Looper.prepareMainLooper()*/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());}}// 获取主线程的LoopermLooper = Looper.myLooper();if (mLooper == null) {throw new RuntimeException("Can't create handler inside thread " + Thread.currentThread()+ " that has not called Looper.prepare()");}// Handler的mQueue指向Looper的mQueuemQueue = mLooper.mQueue;mCallback = callback;mAsynchronous = async;}public Handler(@NonNull Looper looper) {this(looper, null, false);}public Handler(@NonNull Looper looper, @Nullable Callback callback) {this(looper, callback, false);}/*** 第二种构造方法,给在子线程中创建Handler时使用,子线程要自主调用Looper.prepare()*/@UnsupportedAppUsagepublic Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {mLooper = looper;mQueue = looper.mQueue;mCallback = callback;mAsynchronous = async;}
- 发送消息
发送消息有几种方式,但是归根结底都是调用了sendMessageAtTime()
方法。在子线程中通过Handler
的post()
方式或send()
方式发送消息,最终都是调用了sendMessageAtTime()
方法。
post方法:
public final boolean post(@NonNull Runnable r) {return sendMessageDelayed(getPostMessage(r), 0);}public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {return sendMessageAtTime(getPostMessage(r), uptimeMillis);}public final boolean postAtTime(@NonNull Runnable r, @Nullable Object token, long uptimeMillis) {return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);}public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {return sendMessageDelayed(getPostMessage(r), delayMillis);}public final boolean postDelayed(Runnable r, int what, long delayMillis) {return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);}public final boolean postDelayed(@NonNull Runnable r, @Nullable Object token, long delayMillis) {return sendMessageDelayed(getPostMessage(r, token), delayMillis);}
send方法:
public final boolean sendMessage(@NonNull Message msg) {return sendMessageDelayed(msg, 0);}public final boolean sendEmptyMessage(int what){return sendEmptyMessageDelayed(what, 0);}public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {Message msg = Message.obtain();msg.what = what;return sendMessageDelayed(msg, delayMillis);}public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {Message msg = Message.obtain();msg.what = what;return sendMessageAtTime(msg, uptimeMillis);}public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {if (delayMillis < 0) {delayMillis = 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}
就连子线程中调用Activity
中的runOnUiThread()
更新UI,其实也是发送消息通知主线程更新UI,最终也会调用sendMessageAtTime()
方法。
/*** 如果当前的线程不等于UI线程(主线程),就去调用Handler的post()方法,最终会调用sendMessageAtTime()方法。* 否则就直接调用Runnable对象的run()方法。*/
public final void runOnUiThread(Runnable action) {if (Thread.currentThread() != mUiThread) {mHandler.post(action);} else {action.run();}
}
sendMessageAtTime()
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {// 其中mQueue是消息队列,从Looper中获取的MessageQueue queue = mQueue;if (queue == null) {RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");Log.w("Looper", e.getMessage(), e);return false;}// 调用enqueueMessage方法return enqueueMessage(queue, msg, uptimeMillis);}private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis) {// 把自己(Handler)传入消息一并发送,因为Looper需要用Handler来执行dispatchMessage()msg.target = this;msg.workSourceUid = ThreadLocalWorkSource.getUid();if (mAsynchronous) {msg.setAsynchronous(true);}// 调用MessageQueue的enqueueMessage方法return queue.enqueueMessage(msg, uptimeMillis);}
可以看到sendMessageAtTime()
方法的作用很简单,就是调用MessageQueue
的enqueueMessage()
方法,往消息队列中添加一个消息。