Android异步消息传递机制

Handler的异步消息传递机制

MessageQueue工作原理

  • MessageQueue主要包含两个操作:插入和读取。读取操作本身会伴随着删除操作,插入和读取对应的方法分别为enqueueMessage和next,其中enqueueMessage的作用是往消息队列中插入一条消息,而next的作用是从消息队列中取出一条消息并将其从消息队列中移除。尽管MessageQueue叫消息队列,但是它的内部实现并不是用的队列,实际上它是通过一个单链表的数据结构来维护消息列表,单链表在插入和删除上比较有优势。
  1. enqueueMessage方法的主要操作其实就是单链表的插入操作。
  2. next方法是一个无限循环的方法,如果消息队列中没有消息,那么next方法会一直阻塞在这里。当有新消息到来时,next方法会返回这条消息并将其从单链表中移除。
    在这里插入图片描述
    在这里插入图片描述

Looper工作原理

  • Looper在Android的消息机制中扮演着消息循环的角色,具体来说就是它会不停地从MessageQueue中查看是否有新消息,如果有新消息就会立刻处理,否则就一直阻塞在那里。
  • 在构造方法中它会创建一个MessageQueue,即消息队列,然后将当前线程的对象保存起来。
    在这里插入图片描述
  • 通过Looper.prepare,即可为当前线程创建一个Looper,接着通过Looper.loop()来开启消息循环,Looper除了prepare方法外,还提供了prepareMainLooper方法,这个方法主要是给主线程也就是ActivityThread创建Looper使用的,其本质也是通过prepare方法来实现的。由于主线程的Looper比较特殊,所以Looper提供了一个getMainLooper方法,通过它可以在任何地方获取到主线程的Looper。
  • Looper也是可以退出的,Looper提供了quit和quitSafely来退岀一个Looper,二者的区别是:quit会直接退出Looper,而quitSafely只是设定一个退出标记,然后把消息队列中的已有消息处理完毕后才安全地退出。在子线程中,如果手动为其创建了Looper,那么在所有的事情完成以后应该调用quit方法来终止消息循环,否则这个子线程就会一直处于等待的状态,而如果退出Looper以后,这个线程就会立刻终止。
  • loop方法是一个死循环,唯一跳岀循环的方式是MessageQueue的next方法返回了null。当Looper的quit方法被调用时,Looper就会调用MessageQueue的quit或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,它的next方法就会返回null。也就是说,Looper必须退出,否则loop方法就会无限循环下去。loop方法会调用MessageQueue的next方法来获取新消息,而next是一个阻塞操作,当没有消息时,next方法会一直阻塞在那里,这也导致loop方法一直阻塞在那里。如果MessageQueue的next方法返回了新消息,Looper就会通过msg.target.dispatchMessage(msg)处理这条消息,这里的msg.target是发送这条消息的Handler对象,这样Handler发送的消息最终又交给它的dispatchMessage方法来处理了。但是这里不同的是,Handler的dispatchMessage方法是在创建Handler时所使用的Looper中执行的,这样就成功地将代码逻辑切换到指定的线程中去执行了。
    [image:0551119B-2F44-456D-811E-EE2D279CEE11-547-00000B99E7F80D08/C0F72944-7C71-4C73-81CB-85639F5699B6.png]

Handler工作原理

  • Handler工作主要包含消息的发送和接收过程。
  • 消息的发送可以通过post的一系列方法以及send的一系列方法来实现,post的一系列方法最终是通过send的一系列方法来实现的。
    在这里插入图片描述
  • Handler发送消息的过程仅仅是向消息队列中插入了一条消息,MessageQueue的next方法就会返回这条消息给Looper,Looper收到消息后就开始处理了,最终消息由Looper交由Handler处理,即Handler的dispatchMessage方法会被调用,这时Handler就进入了处理消息的阶段。


    首先,检查Message的callback是否为null,不为null就通过handleCallback来处理消息。Message的callback是一个Runnable对象,实际上就是Handler的post方法所传递的Runnable参数。其次,检查mCallback是否为null,不为null就调用mCallback的handleMessage方法来处理消息。Callback是个接口。通过Callback可以采用如下方式来创建Handler对象:Handler handler=new Handler(callback)。Callback可以用来创建一个Handler的实例但并不需要派生Handler的子类。在日常开发中,创建Handler最常见的方式就是派生一个Handler的子类并重写其handleMessage方法来处理具体的消息,而Callback给我们提供了另外一种使用Handler的方式,当我们不想派生子类时,就可以通过Callback来实现。最后,调用Handler的handleMessage方法来处理消息。
  • Handler还有一个特殊的构造方法,那就是通过一个特定的Looper来构造Handler,通过这个构造方法可以实现一些特殊的功能。
  • Handler的默认构造方法会调用下面的构造方法,很明显,如果当前线程没有Looper的话,就会抛出异常,这也解释了在没有Looper的子线程中创建Handler会引发程序异常的原因。
    [image:CD12A8EB-247F-4D84-8B8C-28EAAFAB83D8-547-00000CE809FD55BC/58BF6441-AF2D-4C7F-9D8B-D83AA61CE946.png]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章