美文网首页源码分析Android题库
Android Handler消息机制,你知道多少

Android Handler消息机制,你知道多少

作者: Alsan_L3 | 来源:发表于2022-02-22 23:09 被阅读0次
1. Handler使用

在Activity中实例化一个Handler并实现他的handleMessage方法,然后在需要调用的地方通过使用sendpost系列方法,就可以轻松的将一个任务切换到Handler所在的线程中去,如下:

    private val handler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
        }
    }

    handler.send*();
    handler.post*();

so easy!
然而,你真的了解Handler了吗,真的用好了吗,真的没有踩过Handler的坑?带着这些疑问,我们今天再来重新认识下Handler。

2. 消息机制的模型和架构

消息机制主要包含以下4个部分:Handler、Message、Looper、MessageQueue;下面我们一一介绍:

  • Handler:消息辅助类,主要功能是向消息池发送各种消息事件;
  • Message:需要传递的消息及数据的载体;
  • Looper:不断循环执行(Looper.loop()),从MessageQueue中读出消息,按分发机制分发给不同的消息处理者;
  • MessageQueue:消息队列,内部是通过一个单链表实现的,主要作用是向消息池投递消息(MessageQueue.enqueueMessage)和取走消息(MessageQueue.next)。
运行机制:在子线程执行完耗时操作时,通过Handler发送消息出去,将会调用MessageQueue.enqueueMessage向消息对列中添加消息,Looper通过loop()方法开启循环后,不断的从消息池中读取消息(MessageQueue.next),然后调用目标Handler的dispatchMessage传递消息,返回到Handler所在线程,目标Handler接收到消息后,通过handleMessage处理消息,如下图: Handler运行机制
3. 消息机制源码分析
  • 在主线程创建Handler后,ThreadLocal会自动调用Looper.prepare()创建Looper;
  • 通过send或post方法发送消息后,最终通过sendMessageAtTime中的enqueueMessage方法将消息发送到消息池中;
  • 在Looper中启动循环,通过loop()方法不断获取消息;
  • 拿到消息后通过msg.target.dispatchMessage将消息分发到目标Handler中进行处理
4. 消息机制如何引起内存泄漏及解决方案
  • 引起原因:Handler允许我们发送延时消息,在延时期间关闭了Activity,这时因为Message会持有Handler,另外Java特性内部类会持有外部类,使得Handler会持有Activity,最终导致泄漏。
  • 解决方案:将Handler定义成静态内部类,在内部持有Activity弱引用,同时及时移除所有消息,代码如下:
    private val handler = SafeHandler(this)

    private class SafeHandler(activity: Activity?) : Handler() {
        private val ref: WeakReference<Activity?>
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            if (ref.get() != null) {
            }
        }

        init {
            ref = WeakReference(activity)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacksAndMessages(null)
    }
5. 如何在子线程中更新UI
  • Toast和Dialog在子线程中弹出
        Thread(Runnable {
            Looper.prepare()
            Toast.makeText(this, "不会崩溃啦!", Toast.LENGTH_SHORT).show()
            Looper.loop()
        })
  • 通过在子线程中将数据post出来再执行
UiHandler.run(runnable);
6. Looper机制妙用
import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;

public final class UiHandler {
    private UiHandler(){

    }
    private static final Handler HANDLER = new Handler(Looper.getMainLooper());

    public static void run(@NonNull Runnable runnable) {
        if (isMainThread()) {
            runnable.run();
        }else{
            HANDLER.post(runnable);
        }
    }

    public static boolean isMainThread() { 
        return Looper.myLooper() == Looper.getMainLooper(); 
    }
}
7. Handler延伸
  • AsyncTask:
  • HandlerThread:
  • Messager:
  • IdleHandler:
  • IntentService:

上述Handler延伸可自行查找资料,这里不再一一讲述

8.自己实现一套消息机制

通过上面的分析,我们是否可以参考源码,试着自己实现一套简单的消息机制呢,欢迎大家踊跃参与!

相关文章

网友评论

    本文标题:Android Handler消息机制,你知道多少

    本文链接:https://www.haomeiwen.com/subject/flxnlrtx.html