当前位置: 首页 > 工具软件 > Android-Next > 使用案例 >

Android的消息机制(原理描述篇)

堵雅健
2023-12-01

概述

Android的消息机制是由Handler+MessageQueue+Looper三个成为整体共同协作的工作过程。其中Handler可将一个任务切换到指定的线程中去。

在日常开发中,我们都知道系统规定我们必须在主线程(UI线程)中去操作UI控件,同时不建议我们在主线程中执行耗时的操作。
为什么不能在子线程中更新UI呢?因为UI控件是不安全的,但是如果用锁的机制又会影响访问的效率和逻辑变得复杂。ViewRootImpl对UI操作做了验证,验证的方法是checkThread来完成的。

消息的发送

  • Handler调用send方法发送消息
  • send方法会调用MessageQueue的enqueueMessage方法将消息放入消息队列中去
  • Looper发现有新的消息时,到最后会调用Runable或者Handler的handlerMessage方法
    其中Looper是运行在创建Handler所在的进程中

    ThreadLocal的工作原理

    ThreadLocal:是一个线程内部的数据储存类,他可以把数据储存到指定的线程中去,然后
    在指定的线程才能获取保存在该线程中的数据,其他线程访问不到这些数据。

在Looper、ActivityThread的、AMS都用到了ThreadLocal。

ThreadLocal用法:它可以指定要操作的类型,在不同线程中设置不同的值。

  • set方法
    1.获取当前线程
    2.根据当前线程获取Values(内部类)对像
    3.将ThreadLocal的值储存到table(Object[])数组中去
    4.将ThreadLocal的引用储存在table[index]中
    5.将ThreadLocal的value保存在table[index+1]中

  • get方法
    1.获取当前线程
    2.根据当前线程获取指定的Values对象
    3.找到ThreadLocal中引用对象在table中的位置,然后在下一个位置找到ThreadLocal的值

消息队列的工作原理

消息队列在Android中指的是MessageQueue:

  • 插入消息
    enqueueMessage方法:往消息队列中插入一条消息,其实它就是一个链表的插入操作
  • 读取消息
    next方法:从消息队列中取出一条消息并且从队列中移除该消息它会无限循环,如果消息队列没有消息,则它会阻塞在这里当有新的消息来时,它会返回这条消息并从链表中移除。

Looper的工作原理

Looper在Android的消息机制中扮演着消息循环的角色,不停地从MessageQueue中查看是否有新消息

在Looper在构造方法中它会创建一个MessageQueue,并将当前的线程保存起来

通过Looper.prepar()即可创建一个Looper,接着通过Looper.loop()来开启消息循环

Looper中的PrepareMainLooper方法,主要是给主线程使用的,它的本质也是prepare方法来实现的,
Looper还提供一个getMainLooper方法来获取主线程的Looper。

退出Looper

  • quite方法:直接退出Looper
  • quitSafely方法:设定一个退出标记,然后把消息队列中的消息处理完之后再安全退出

    建议在不需要的时候终止Looper
    

    loop方法:里面是一个死循环,唯一能够跳出来的条件是MessageQueue的next方法返回null。 当调用 Looper的quit方法时,MessageQueue的quit或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,它的next方法会返回null。

在源码中:其中有msg.target,这是一个Handler,它调用dispatchMessage方法,即将消息交由这个方法处理。

Handler的工作原理

Handler发送消息:仅仅是向消息队列插入一条消息,MessageQueue的next方法将消息传给Looper,Looper将收到的消息进行处理,然后交由Handler(dispatchMessage方法)。

Handler处理消息的过程

  1. 检查它的callback是否为空,不为空即通过handlerCallback方法来处理消息
  2. 检查mCallback是否为空,如果不为空即调用mCallback的handleMessage方法处理消息
  3. 调用Handler的handleMessage方法来处理消息

Handler的特殊构造方法:this(looper,null,false),这就说明了如果当前线程没有Looper的话,则会抛出异常

主线程的消息循环

  • Activity的主线程就是ActivityThread,入口为main方法

  • main方法里面通过Looper.preparMainLooper来创建主线程的Looper和MessageQueue,然后调用Looper.loop方法进行主线程的消息循环

  • ActivityThead.H是一个Handler,内部定义了一组消息类型,主要包含四大组件的启动和停止

  • ActivityThread通过ApplicationThread和AMS进行进程间的通信

  • AMS->回调ApplicationThread中的Binder方法->ApplicationThread向H发送消息->H将逻辑切换到ActivityThread中执行

 类似资料: