Android Handler的机制跟源码分析

一、消息机制

        在应用启动时,会执行 main() 方法, main() 会创建一个 Looper 对象,然后开启一个死循环,目的是不断从 消息队列  MessageQueue 里面取出 Message 对象并处理。

        在Android中使用消息机制,会优先想到的是Handler。Handler可以轻松的将一个任务切换到Handler所在的线程去执行。在多线程的应用场景中,可以将工作线程中需要更新UI的操作信息传递到主线程去执行,从而实现工作线程更新UI的操作,最终实现异步消息的处理。

二. Handler机制模型

消息机制主要包含Handler、Message、MessageQueue,Looper这四个类。

  • Handler:消息辅助类。主要功能将 Message 对象发送到 MessageQueue 中,同时将自己的引用赋值给 Message#target (Handler.sendMessage())。也可以实现 handleMessage() 方法处理回调。

  • Message:消息实体。需要传递的消息也可以传递数据。

  • MessageQueue:消息队列。**内部实现并不是队列,而是利用单链表去实现因为在插入和删除数据有优势。**用于存储Handler发给来的消息( Message )以及取出。 内部使用单链表实现 

  • Looper:与线程绑定,不止局限于主线程,绑定的线程来处理 Message 。不断循环执行 Looper.loop() ,从 MessageQueue 中读取 Message ,按分发机制将消息分发出去给目标处理(将 Message 发到 Handler.dispatchMessage 方法去处理)。

三、Handler运行流程

工作流程: 异步通信准备==>消息入队==>消息循环==>消息处理

1.异步通信准备

假定在主线程创建Handler,则会直接在主线程中创建 Looper , MessageQueue 和 Handler 对象。Looper和MessageQueue对象均属于其 创建线程 (由主线程创建则属于主线程)。创建 Looper 时会自动创建 MessageQueue 对象,创建好 MessageQueue 对象后, Looper 自动进入循环。 Handler 自动绑定 Looper 以及 MessageQueue 。

 Looper 对象的创建方法一般通过 Looper.prepareMainLooper() 和 Looper.prepare() 方法。

2.消息入队

工作线程通过 Handler 发送 Message 到 MessageQueue 中。消息内容一般是UI操作,通过 Handler.sendMessage(Message message) 或 Handler.post(Runable r) 发送。加入 MessageQueue 一般通过 MessageQueue.enqueueMessage(Message msg,long when) 操作。

3.消息循环

分为消息出队和消息分发两个步骤

  • 消息出队: Looper 从 MessageQueue 中循环取出 Message 

  • 消息分发: Looper 将取出的 Message 分发给创建消息的 Handler 

消息循环过程中, MessageQueue 为空,则线程堵塞

4.消息处理

 Handler 接受发过来的 Message 并处理。

四、Handler源码解析

1. 创建循环器对象( Looper )和创建消息队列对象( MessageQueue )

创建Looper对象主要有两个方法: Looper.prepareMainLooper() 和 Looper.prepare() 

创建MessageQueue对象方法:创建Looper对象时会自动创建MessageQueue

// 源码位置:../core/java/android/os/Looper.java
 
final MessageQueue mQueue;
final Thread mThread;
//Looper对象创建时会自动创建一个MessageQueue对象。
private Looper(boolean quitAllowed) {
     mQueue = new MessageQueue(quitAllowed);
     mThread = Thread.currentThread();
    }
 
//为当前线程(子线程)创建一个Looper对象 需要在子线程中主动调用该方法
public static void prepare() {
        prepare(true);
    }
 
private static void prepare(boolean quitAllowed) {
    //判断sThreadLocal是否为null,不为空则直接跑出异常 可以保证一个线程只可以调用一次prepare方法
    if (sThreadLocal.get() != null) {
          throw new RuntimeException("Only one Looper may be created per thread");
       }
    sThreadLocal.set(new Looper(quitAllowed));
    }
 
//为主线程创建一个Looper对象 该方法会在主线程创建时自动调用
public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

    1. 创建Looper对象时会自动创建MessageQueue对象

    2.主线程的Looper对象是自动生成的,而子线程需要调用Looper.prepare()创建Looper对象

    创建主线程是调用了ActivityThreadmain()方法。

    然后按照流程调用了Looper.prepareMainLooper()Looper.loop()。所以主线程不需要调用代码生成

    Looper对象。

    3.Handler的主要作用是( 在主线程更新UI ),所以Handler主要是在主线程创建的。

    4.Looper与Thread是通过 ThreadLocal 关联的。由于 ThreadLocal 是与线程直接关联的,

    参考 prepare() 。

    5.子线程创建Handler对象:无法在子线程直接调用Handler无参构造方法Handler创建时需要绑定Looper对象 。需要使用 HandlerThread 。

    //源码位置: ../core/java/android/app/ActivityThread.java
     public static void main(String[] args) {
         ...
          Looper.prepareMainLooper();
          Looper.loop();
         ...
     }

    2.开启Looper即消息循环

            创建了 Looper和MessageQueue 

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包

    打赏作者

    踏雪羽翼

    你的鼓励将是我创作的最大动力

    ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
    扫码支付:¥1
    获取中
    扫码支付

    您的余额不足,请更换扫码支付或充值

    打赏作者

    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值