Skip to content

Latest commit

 

History

History
41 lines (36 loc) · 4.15 KB

06-消息队列.md

File metadata and controls

41 lines (36 loc) · 4.15 KB

消息队列机制

  1. MessageQueue内部存储了一组消息,以队列的形式对外提供插入和删除操作(不是真正的队列,而是单链表实现)。
  2. Looper会以无限循环的形式去查找是否有新消息,如果有就处理,否则就一直等待。
  3. Handler创建的时候会采用当前线程的Looper来构造消息循环系统(通过ThreadLocal)。
  4. ThreadLocal可以在不同线程中互不干扰的存储并提供数据。
  5. 不给UI线程加锁的原因:加锁会让UI线程访问逻辑变的复杂;锁机制会降低UI线程访问的效率。
  6. Handler通过post方法(本质也是调用send方法)或send方法发送消息,send方法调用MessageQueue的queueMessage方法将消息放入队列,然后Looper发现消息来时,就会处理该消息,最后消息的Runable或者HandlerMessage方法就会被调用。
ThreadLocal
  1. ThreadLocal是一个线程内部的数据存储类,通过他可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据。
  2. 当某些数据是以线程为作用域并且不同的线程有不同的副本的时候,就可以考虑采用ThreadLocal。
  3. 从ThreadLocal的 set和get方法中可以看出,他们所操作的对象都是当前线程的localValues的table数组,因此在不同线程中访问同一个ThreadLocal的set和get方法,他们对ThreadLocal所做的读写操作仅限于各自线程的内部。
MessageQueue
  1. MessageQueue主要操作包括插入和读取,读取操作本身伴随着删除操作。插入和读取的方法分别对应enqueueMessage和next。
  2. enqueueMessage的实现,主要操作就是对单链表的插入操作。
  3. next方法是一个无限循环的方法,如果消息队列中没有消息,next方法便会一直阻塞在这里。当有新消息来时,next方法会返回这条消息并将其从单链表中移除。
Looper
  1. Looper的构造方法中为当前线程创建MessageQueue,然后将当前线程保护起来。
  2. 通过Looper.prepare()即可为当前线程创建一个Looper,接着通过Loop.loop()来开启消息循环(此时Loop才生效)。
  3. Looper提供退出方法:quit和quitSafely。quit直接退出,quitSafely设定一个标记,消息处理完后才退出。
  4. Looper退出后,通过Handler发送(send)的消息会失败,返回flase。
  5. Looper退出后,线程会终止。
  6. Looper处理next方法返回的消息:msg.target.dispatchMessage(msg),msg.taget即发送这条消息的Handler。
Handler
  1. Handler处理消息流程:检查callback是否为空,不为空就通过handlercallback来处理消息,该callback即位Handler通过Post传递的Runable。
  2. 通过callback可以如此创建Handler:Handler handler = new Handler(callback)。
  3. 通过该callback可以创建一个Handler实例而不派生Handler子类(创建Handler的子类并重写handleMessage方法)。
主线程消息循环
  1. Looper.loop()的死循环,保证此线程一直在执行不会被退出(跳出死循环的方法是MessageQueue的next方法返回null)。
  2. 如何处理其他事务:创建新线程。
  3. 真正会卡死主线程的操作是在回调方法生命周期里操作时间过长,会导致掉帧或ANR。
  4. ActivityThread.Main中,在进入死循环之前便创建了Binder线程。
  5. 基于Linux底层的机制,主线程的死循环并不消耗资源,大部分时间处于休眠状态。
  6. Activity的生命周期是怎么实现在死循环体之外执行的:通过Handler机制。
  7. Android的主线程是ActivityThread,入口方法为Main,在Main方法中初始化Looper和MessageQueue。
  8. 主线程的handler就是ActivityThread.H,它内部定义了一组消息类型,包含了四大组件的生命周期。
  9. ActivityThread通过ApplicationThread和AMS进行线程间通信,AMS以进程间通信的方式完成ActivityThread的请求后回调Application中的Binder方法,然后ApplicationThread会向H发送消息,H收到消息后会将ApplicationThread中的逻辑切换到ActivityThread中执行,即切换到主线程中执行,这个过程就是主线程的消息循环模型。