Handler MessageQueue Looper 学习

文章目录
  1. 1. 一、介绍
  2. 2. 二、 Handler
    1. 2.1. sendMessage 和 post
    2. 2.2. dispatchMessage(Message msg)
    3. 2.3. Callback
  3. 3. 三、MessageQueue
    1. 3.1. 插入数据
    2. 3.2. 返回数据
  4. 4. 四、 Looper
    1. 4.1. ThreadLocal
    2. 4.2. prepare()
    3. 4.3. prepareMainLooper()
    4. 4.4. loop()

一、介绍

Handler MessageQueue Looper 在 Android 中板扮演着不同线程间传递消息的角色,最常见的就是在子线程和 UI 线程之间的消息交流,原理就是一个线程发消息,另一个线程取消息。

二、 Handler

Handler 作用是对消息队列里的数据进行插入

sendMessage 和 post

不管发消息用 sendMessage 还是 post 其最终是调用 MessageQueue 的 enqueueMessage() 方法,这里发送消息时,MessageQueue 队列里有数据了就会调用 Looper 中的 loop() 方法来取出数据 ,然后分发处理

dispatchMessage(Message msg)

  • 分发处理消息

dispatchMessage

先判断消息里是否含有 Callback,(这里的 Callback 其实是一个 Runable 类型,例如我们经常 post(new Runable) 这种写法),如果含有,那就将消息交给 handleCallback()处理,不含有就重新派生一个handler,并重写 handlerMessage进行处理。

Callback

Callback

当我们查看到 Callback 这接口的时候,发现还有它里面还有一个 handleMessage(Message msg) 抽象方法,那么我们也可以在不需要创建 一个 Handler 子类 的时候去进行消息的处理。

三、MessageQueue

说到 MessageQueue 那肯定离不开 Message 而 Message 恰好在 MessageQueue 类中出现了, Message 其实是一个单链表,其实现了 Android 的 Parcelable 的序列化接口,既然 Message 是链表形式,那么 MessageQueue 应该就好理解了,MessageQueue 就是对这个链表进行操作的而存在的。

插入数据

enqueueMessage(Mesage msg, long when){}

先是判断链表是否为空,为空的话就插入数据,不为空就就一直循环着,因为我们知道 MessageQueue 是消息队列,它就是循环的“ 处理 ” 消息用的(不是循环 “ 发送 ”消息, 发送传递消息是 Looper 干的)而不为空的情况下,其会根据数据存放的先后进行数据处理,就是先存入的先处理。依此循环。

返回数据

Message next() {}

返回数据也是一个循环,(这里的返回数据不是直接向线程需要数据的地方返回),但这个循环多了个阻塞方法 nativePollOnce(ptr, nextPollTimeoutMillis); 这是 native 方法 ,一般在调用该方法之前会先调用 Binder.flushPendingCommands();

不管是插入数据还是返回数据其实都是基于 Meesage 这个单链表来展开操作。而Message 的链表的 next 方法,在 package 中已经封装好了,所以 MessageQueue 的理解就更加简单了,其就本意就是对链表里的数据进行有条件的取出和插入,这是一个循环的过程。

四、 Looper

在讲 Looper 之前 先来知道一个事情 ,就是不同的线程会有不同的 Looper 对象,前提是我们 Looper.prepare() 创建了 Looper 对象。那么问题来了,那么多线程就会有那么多的 Looper 对象,要怎么保存才好呢?

ThreadLocal

一个线程对应一个实例 那就最好用 ThreadLocal 了,而源码中使用的正是ThreadLocal

prepare()

创建一个 Looper 对象并保存到 ThreadLocal 集合中去。

prepareMainLooper()

创建主线程的 Looper 对象

在 prepare() 和 prepareMainLooper() 方法中看到都调用了一个 prepare 的重载方法,其参数是一个 boolean 类型,翻译过来可以认为是 “能否退出”,在 prepareMainLooper() 中传入的是一个 false, prepare() 传入的是 true ,false 意味该 looper 可以退出,而主线程的 looper 为 false 意味着主线程不能退出,会一致循环 looper。

当看到在创建 MessageQueue 实例的地方,需要一个退出确认参数 quitAllowed ,一路追踪,最终到了 MessageQueue 里的 quit 方法,通过这个方法知道:要退出整个过程,需要移除所有的 MessagesLocked,而主线城的 Looper 对象是退出不了的;如果主线程的 Looper 实例能退出销毁,那应用绝对 Crash。

loop()

看到方法 loop() 里面是一个死循环,队列有消息就取出消息,并判断消息的 taget 交给 Handler 分发处理 ,没有消息就 return 继续循环取下一个消息。