android消息机制是指Handler的运行机制,需要MessageQueue以及Looper的支撑,开发中常用于更新UI。
- UI控件不是线程安全的,所以采用单线程(主线程)处理UI操作
- android中主线程,即UI线程,就是ActivityThread (其创建时会初始化Looper, 具体在main方法入口)
1.Handler
Handler的作用就是发送 & 接收消息 (android.os.Handler代码示例)
1.1 发送消息
两种发送方法(本质都是一样):
- 一系列的sendMessage
- 一系列的post(Runnable)
// 有多个sendMessage方法,这里列举其一
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
// 有多个post方法,这里列举其一
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
// Runnable与Message的对应关系
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
// 各种发送方法,最终会调用此方法,即将消息插入MessageQueue
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
2.2 接收消息
消息插入到MessageQueue,Looper调用mQueue.next()将消息交给Handler处理,即Handler#dispatchMessage会调用,handleMessage是需要用户自己实现具体消息的处理。
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(@NonNull Message msg) {
}
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
// msg.callback即为post过来的Runnable
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
2.Handler/MessageQueue/Looper如何关联
2.1 Looper在初始化时,会创建MessageQueue
// Looper.prepare()内部会调用Looper构造方法,在构造方法内创建MessageQueue
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
2.2 Handler在初始化时,会获取当前线程的Looper,进而可以获取MessageQueue
/**
* Default constructor associates this handler with the {@link Looper} for the
* current thread.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*/
public Handler() {
this(null, false);
}
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 以及 MessageQueue
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
2.3 Handler运行在哪个线程取决于Looper
3.总结
- 一个线程只有一个Looper,但是可以创建多个Handler;
- 消息不会错乱,因为消息自身带有各自handler标识 msg.target.disaptchMessage(msg)
- 两种方式解决Handler内存泄漏:静态内部类+弱引用,外部类结束生命周期时清空消息队列