Handler消息机制源码分析
Handler消息机制源码分析
一、概述
Handler消息机制是Android系统中最重要的特性之一,它主要用于解决Android单线程模型中的线程间通信问题。本文将深入分析Handler消息机制的源码实现,帮助你理解其工作原理。
二、基础知识
2.1 Handler消息机制的核心类
- Handler:消息处理者,负责发送和处理消息
- Message:消息对象,包含要传递的信息
- MessageQueue:消息队列,用于存储消息
- Looper:消息循环器,不断从MessageQueue中取出消息并交给Handler处理
2.2 基本工作流程
- Handler发送消息到MessageQueue
- Looper不断从MessageQueue中取出消息
- Handler处理Looper分发来的消息
三、源码分析
3.1 Handler的创建
class MainActivity : AppCompatActivity() {
private val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
when (msg.what) {
MSG_UPDATE_UI -> updateUI()
}
}
}
}
源码中Handler的构造过程:
public Handler(@Nullable Looper looper) {
this(looper, null, false);
}
public Handler(@Nullable Looper looper, @Nullable Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
3.2 消息的发送过程
// 发送消息的几种方式
handler.sendMessage(msg)
handler.sendEmptyMessage(what)
handler.sendMessageDelayed(msg, delayMillis)
handler.post(runnable)
源码分析:
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
return enqueueMessage(queue, msg, uptimeMillis);
}
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);
}
3.3 MessageQueue的工作原理
MessageQueue是一个优先级队列,按照消息的执行时间排序。
boolean enqueueMessage(Message msg, long when) {
// 省略参数检查代码
synchronized (this) {
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
// 根据时间顺序将消息插入队列
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
}
msg.next = p;
prev.next = msg;
}
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
3.4 Looper的消息循环
Looper负责从MessageQueue中取出消息并分发给Handler处理。
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // 可能阻塞
if (msg == null) {
return;
}
try {
msg.target.dispatchMessage(msg);
} finally {
msg.recycleUnchecked();
}
}
}
四、实战案例
4.1 异步任务处理
class ImageLoadActivity : AppCompatActivity() {
private val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
when (msg.what) {
MSG_LOAD_SUCCESS -> {
val bitmap = msg.obj as Bitmap
imageView.setImageBitmap(bitmap)
}
MSG_LOAD_FAILED -> {
Toast.makeText(this@ImageLoadActivity, "加载失败", Toast.LENGTH_SHORT).show()
}
}
}
}
private fun loadImage() {
Thread {
try {
val bitmap = loadImageFromNetwork()
val msg = Message.obtain()
msg.what = MSG_LOAD_SUCCESS
msg.obj = bitmap
handler.sendMessage(msg)
} catch (e: Exception) {
handler.sendEmptyMessage(MSG_LOAD_FAILED)
}
}.start()
}
companion object {
const val MSG_LOAD_SUCCESS = 1
const val MSG_LOAD_FAILED = 2
}
}
4.2 延时任务处理
class CountDownActivity : AppCompatActivity() {
private var countDown = 60
private val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
when (msg.what) {
MSG_COUNT_DOWN -> {
countDown--
tvCountDown.text = "${countDown}s"
if (countDown > 0) {
sendEmptyMessageDelayed(MSG_COUNT_DOWN, 1000)
}
}
}
}
}
override fun onDestroy() {
super.onDestroy()
handler.removeCallbacksAndMessages(null)
}
companion object {
const val MSG_COUNT_DOWN = 1
}
}
五、调试技巧
5.1 使用Looper.getMainLooper().setMessageLogging()跟踪消息
Looper.getMainLooper().setMessageLogging { log ->
Log.d("MessageLogging", log)
}
5.2 使用systrace工具分析消息处理耗时
TraceCompat.beginSection("handleMessage")
try {
// 处理消息
} finally {
TraceCompat.endSection()
}
六、性能优化
6.1 避免内存泄漏
- 使用静态内部类+弱引用
- Activity销毁时移除消息
- 使用LifecycleOwner管理Handler生命周期
class SafeHandler(lifecycleOwner: LifecycleOwner, private val callback: Handler.Callback) : Handler(Looper.getMainLooper()) {
private val lifecycleRef = WeakReference(lifecycleOwner)
init {
lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onDestroy(owner: LifecycleOwner) {
removeCallbacksAndMessages(null)
}
})
}
override fun handleMessage(msg: Message) {
lifecycleRef.get()?.let { lifecycle ->
if (lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)) {
callback.handleMessage(msg)
}
}
}
}
6.2 消息复用
使用Message.obtain()而不是new Message()
val msg = Message.obtain()
try {
msg.what = MSG_TYPE
msg.obj = data
handler.sendMessage(msg)
} catch (e: Exception) {
msg.recycle()
}
七、常见面试题
7.1 Handler实现原理?
答:Handler的实现主要基于消息队列模型,包含四个核心组件:
- Handler:消息处理者,负责发送和处理消息
- Message:消息对象,存储消息的内容和元数据
- MessageQueue:消息队列,按时间顺序存储消息
- Looper:消息循环器,不断从队列中取出消息并分发给Handler
工作流程:
- Handler发送消息,消息进入MessageQueue
- Looper不断循环从MessageQueue中取出消息
- 消息分发给对应的Handler处理
7.2 Handler引起的内存泄漏原因及解决方案?
答:
原因:
- Handler作为内部类持有外部Activity的引用
- 发送延迟消息后Activity销毁,而消息队列中的Message持有Handler引用,Handler又持有Activity引用
解决方案:
- 使用静态内部类+弱引用
- Activity销毁时清空消息队列
- 使用LifecycleOwner管理Handler生命周期
7.3 Handler线程切换原理?
答:
- 每个线程可以通过Looper.prepare()创建Looper对象
- Looper对象包含一个MessageQueue
- Handler在构造时关联了Looper对象
- 消息会被发送到Looper关联的MessageQueue
- Looper所在线程通过loop()方法不断取出消息并处理
因此,Handler发送的消息在哪个线程被处理,取决于Handler构造时传入的Looper对象所属的线程。
八、源码分析小结
通过分析Handler消息机制的源码,我们了解到:
- Handler消息机制是一个生产者-消费者模型
- MessageQueue通过单链表实现优先级队列
- Looper通过死循环不断处理消息,但不会导致ANR
- 消息处理过程是同步的,保证了线程安全
- 系统通过ThreadLocal维护Looper,保证线程隔离
掌握Handler消息机制的原理,对于理解Android系统的消息驱动模型和异步编程具有重要意义。在实际开发中,合理使用Handler可以优雅地解决线程间通信问题。
九、参考资源
- Android源码:Handler.java
- Android开发者文档:Handler API Guide
- Android源码分析:Looper.java
本文通过深入分析Handler消息机制的源码实现,结合实际案例和面试题,帮助你全面理解Android消息机制的工作原理。在实际开发中,建议结合本文提供的最佳实践,合理使用Handler,避免常见问题。如果你对Handler机制还有任何疑问,欢迎在评论区留言交流。