美文网首页源码分析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