主页 > 手机  > 

安卓基础组件Looper-01通讯机制简介

安卓基础组件Looper-01通讯机制简介

文章目录 为什么需要 Looper成员MessageQueueLooperHandler lambda 机制图

为什么需要 Looper

main函数/普通函数执行完后,整个进程/线程也就结束了。为了让处理可执行对象的进程/线程长时间运行,需要无限循环加事件通知的机制。

int main() { while(true) { 1. 线程进入休眠状态,等待通知; 2. 其它地方给当前线程发送通知,线程从休眠中唤醒,读取通知,处理通知 3. 进入下一个循环 } return 0; } 成员 MessageQueue

MessageQueue:装message的容器。

使用 pool 享元设计模式。

有消息处理,数量不能过多。pool会超出容量。

根据时间排序,

当message queue队列满的时候,阻塞,直到用户通过next取出消息。

当出队 next方法 被调用,通知MessagQueue可以进行消息的入队。

// frameworks/base/core/java/android/os/MessageQueue.java boolean enqueueMessage(Message msg, long when) {

生产者消费者

入队 生产者:子线程 向消息队列添加消息和Handler

出队 消费者工作线程:工作线程依此轮循,轮询到了MSG就会执行

java 执行了Looper.loop() 的线程(往往是主线程。因此MSG的消费,执行,都在主线程中)cpp Looper::prepare/new Looper的线程

数量关系:(有说法是每个进程只有一个MessageQueue。但我看起来是觉得每个工作线程都有且只有一个MessageQueue)

java

// frameworks/base/core/java/android/os/Looper.java private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } // sThreadLocal.get() will return null unless you've called prepare(). @UnsupportedAppUsage static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

native

class Looper : public RefBase { Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock Looper

在线程(一般是主线程)中执行Looper.loop(),则这个线程就是“工作线程”。可以认为是MSG的消费者:所有的MSG的消费,执行都是在该线程中。

调用了 Looper::loop() 的线程,会从进程的MessageQueue中取出、处理MSG,并执行Hanlder的重载。

因为 MessageQueue 是线程安全的,所以可以有多个线程调用 Looper::loop(),这些线程并行的处理Hanlder。

对于app来说,这个“工作线程”就是主线程。app启动/挂断,一定是从主线程的 main函数 开始的

// frameworks/base/core/java/android/app/ActivityThread.java public static void main(String[] args) { // 准备loop Looper.prepareMainLooper(); Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); // 让loop运行起来. 一直循环,保障进程一直执行,如果退出,说明程序关闭 Looper.loop();

数量关系:进程中可以在进程中指定一个/多个工作线程,每个工作线程拥有一个Looper

一个线程只允许有一套Handler通讯机制,只有一个Looper

在native层 一个线程new多个Looper是不建议的,但神奇的是这往往并不会出错,符合能跑就行的思想。

一个进程可以有多个工作线程,从而一个进程中可有多个Looper

Handler lambda

狭义的来说

Handler是一个类,一个线程有多个 Handler对象 ——设计模式命令模式定义 Handler时,需要指定 Looper 意味着于此同时确定了对应的MessageQueue和工作线程。各个线程怎么区分其中的msg该让哪个Handler执行呢? Handler.sendMessage时会把this(也就是哪个Handler)传递给MessageQueue。所以,才能让对应 Handler 执行其 handleMessage方法

广义来说:Handler是一种线程通信的方案。

作为方案,MessageQueue和Looper也包含其中

实际上是内存共享的方案

MessageQueue这个容器 在同一进程中的线程间是 共享 的,

主线程可以通过loop死循环去不断的访问 MessageQueue。

为什么 wait/notify用处不大:因为handler已经将需要这部分功能进行了Linux层的封装 使用epoll多路IO复用进行管理。

机制图

解决线程之间的通讯:(并不跨进程)

其他跨线程通信:retrofit,eventbus,rxjava都是使用了主线程MainThread的,底层都使用了Handler机制(Looper机制)

标签:

安卓基础组件Looper-01通讯机制简介由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“安卓基础组件Looper-01通讯机制简介