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() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i(TAG, msg.what);
}
};
@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public 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 interception
AndroidOs.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 certificates
final 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().
@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
@UnsupportedAppUsage
private static Looper sMainLooper; // guarded by Looper.class
@UnsupportedAppUsage
final 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.
*/
@Deprecated
public 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. 实例化MessageQueue
mQueue = 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 block
if (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 logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
// .....
try {
// 获取msg的目标Handler,然后用于分发Message
msg.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 {
@UnsupportedAppUsage
final Looper mLooper;
// 这里并没有实例化,指向Lopper的消息队列
final MessageQueue mQueue;
@UnsupportedAppUsage
final Callback mCallback;
final boolean mAsynchronous;
@UnsupportedAppUsage
IMessenger 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) {
}
}
构造函数:
@Deprecated
public Handler() {
this(null, false);
}
@Deprecated
public Handler(@Nullable Callback callback) {
this(callback, false);
}
@UnsupportedAppUsage
public 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());
}
}
// 获取主线程的Looper
mLooper = 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的mQueue
mQueue = 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()
*/
@UnsupportedAppUsage
public 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()
方法,往消息队列中添加一个消息。