27
2017
09

Android开发艺术探索阅读笔记之二:Android的消息机制

1.总领:
Android的消息机制主要是Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支持。
MessageQueue是消息队列,以队列的形式对外提供插入和删除的工作,然而其内部存储采用单链表的数据结构来存储消息列表。
Looper填补了MessageQueue不能处理消息的缺陷,它会以无限循环的形式去查找是否有新消息,如果有的话就处理,没有的话就一直等待,此外Looper还有一个特殊概念就是ThreadLocal,ThreadLocal并不是线程,它的作用是在每个线程中存储数据。Handler创建的时候会采用当前线程的Looper来构造消息循环系统,那么Handler内部怎样获取到当前线程的Looper呢?就是通过ThreadLocal,ThreadLocal可以在不同线程互补干扰地存储并提供数据,通过ThreadLocal可以轻松获取每个线程的Looper。然而线程默认没有Looper,所以在线程使用时,需要为线程创建Looper。
经常提到的主线程(UI线程),它就是ActivityThread,ActivityThread被创建时就会初始化Looper,这就是主线程默认可以使用Handler的原因。
2.产生原因
主线程中(建议)不能进行耗时操作(容易ANR),需要放到子线程,而子线程进行耗时操作完后有不能在子线程更新UI,导致消息机制的产生。
延伸一点:系统为什么不允许在子线程访问UI:
因为Android的UI控件不是线程安全的,如果在子线程并发访问回到之UI控件处于不可预期的状态,那么问题来了,為什麼不上锁?缺点:上锁会让UI访问的逻辑变得复杂,并且锁机制会降低UI访问的效率。鉴于上述缺点,所以采用但线程模型来处理UI操作。
3.Handler工作原理简述
Handler创建时候会带采用当前线程的Looper构建内部的消息循环系统,如果当前线程没有Looper,则会报错;
Handler创建完成后,内部的Looper和MessageQueue就能和Handler一起协同工作了;
通过Handler的send方法或者post发送一个消息或者Runnable,他会调用MessageQueue的enqueueMessage方法将这个消息放入消息队列,然后Looper发现有新消息到来,就会去处理这个消息,最终消息的Runnable或者Handler的HandlerMessage方法就会被调用。这样,子线程的业务逻辑就能切换到创建Handler所在的线程中执行。
4.ThreadLocal
(1)Handler构建时使用ThreadLocal来得到当前线程的Looper的
(2)线程内部的数据存储类
5.消息队列的工作原理
消息队列即MessageQueue,它主要包含两个操作,一个是读取方法next,此方法伴随着删除操作,一个是往消息队列插入一条消息enqueueMessage,单链表在插入和删除上比较有优势。
简要看下单链表和双链表的对照
单链表:只有一个指向下一个结点的指针
双链表:除了指向下一个结点的指针,还有指向前一个结点的指针
6.Looper的工作原理
具体来说就算他会不断从MessageQueue中察看是否有消息,如果有消息就立刻处理,否则一直堵塞。
它的构造方法会创建一个MessgaeQueue,然后将当前线程的对象保存起来。
Looper最重要的一个方法就是loop方法:
这个方法是一个死循环,唯一跳出循环的方法就是MessgaeQueue的next方法返回了null。当Looper的quit方法被调用的,Looper会调用MessageQueue的quit或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,MessageQueue的next就返回null,Looper的loop就会结束。也就是说,Looper必须退出,否则loop方法无限循环下去(那这种机制不是很占有内存?)。loop方法会调用MessageQueue的next方法来获取新消息,而next是一个堵塞操作,没有消息时,next方法会一直堵塞在那里,导致loop方法堵塞。如果MessageQueue返回了新消息,则loop方法会处理这条消息:msg.target,dispatchMessgae(msg),这里的msg.target是发送这条消息的对象,这样Handler发送的消息又交给它的dispatchMessage方法来处理了,但不同的是,Handler的dispatchMessage是在创建Handler时所使用的Looper中执行的,这样就将代码逻辑切换到指定的线程中执行了。
7.Handler的工作原理
handler包含两个操作,发送和接收消息,其中发送又分send和post,post最终也是调用send实现的。
发送:Handler的发送,其实是将消息插入MessageQueue,Looper处理消息,最终Looper将消息交给Handler处理,即Handler的dispatchMessage方法会被调用,这时候Handler就进入了处理消息的阶段。
处理:首先检查Messgae的callback是否为null,部位null就通过handleCallback方法来处理,如果为空,就判断mCallback是否为空,不为空,通过mCallback.handleMessage来处理,为空,则通过handleMessage来处理,这也是我们用的最多的方式。

上一篇:[RK3288][Android6.0] 系统的ANR(Application Not Responding) 下一篇:Android 中LayoutInflater(布局加载器)源码篇之createViewFromTag方法