代码改变世界

消息循环相关

2016-07-20 11:42  cascle  阅读(653)  评论(0编辑  收藏  举报

  消息循环相关三个大类:Looper,MesseageQueue,Handler

Looper是发动机,负责轮询MessageQueue,等待Handler发送来的消息,即消息并不是直接加到MessageQueue里,而是通过Handler间接加入

先看消息循环的基础,Message这个类

Message实现了Parcelable接口

一系列的obtain方法构造消息

copyFrom方法拷贝消息里的某些域

recycle方法将消息放入消息池,各个域归零

还有一系列set/get/peek方法查看/设置私有域

 

再看三个大类

Looper(frameworks/base/core/java/android/os/Looper.java):

Looper提供一些静态函数将Looper类与当前线程绑定,底层依赖的手段的是ThreadLocal

Looper类要先使用prepare方法准备Looper对象,将其与当前线程绑定,然后使用loop方法开始消息循环,不停的从MessageQueue里抽取消息

对于UI主线程,则特别准备了prepareMainlLooper方法,存在一个类静态变量sMainLooper保存主线程的Looper(每次切换或者恢复UI线程后会重新赋值)

 

主要的API还有以下几个作用:

get×××,获取内置的私有变量,包括MessageQueue,关联的thread,UI线程的sMainLooper

myLooper:获取当前的Looper

quit和quitSafely:退出和安全退出loop循环

判断当前线程与Looper线程是否一致

 

 核心函数是loop函数

这个方法会在头尾利用Binder.clearCallingIdentity方法获取当前进程的PID/UID令牌,并比较是否改变,若改变打log提示

随后从MessageQueue的next方法里获取消息,用消息的target的dispatchMessage方法分发消息,最后调用消息的recycleUnchecked方法回收消息到消息队列

 

 

Handler(frameworks/base/core/java/android/os/Handler.java):

Hanlder类可以算是个消息发送/处理中的辅助类,简化过程

Handler类需要与一个线程绑定,媒介是Looper,要是不传Looper就是创建Handler的那个线程

这个类提供获取(构造)消息,发送回调代码(Runnable),发送消息,判断消息是否存在,移除消息,获取Messenger对象,分发消息,处理消息,同步处理消息等方法

由一个接口一个内部类一个静态内部类

接口Callback用来给外部类实现,这样就不需要继承Handler类也可以处理消息了

内部类MessengerImpl用来发送带有sendingUID的消息

静态内部类BlockingRunnable用来实现挂起handler关联的Looper,直到当前消息关联的动作被执行完毕

主要API如下:

dispatchMessage方法分发消息,将消息交给设定好的对象来处理,优先级是Message自带的callback域(Runnable对象),内部Callback接口的handleMessage方法,类里的handleMessage方法

handleMessage方法是空的,要被子类override来重写

obtainMessage方法用来构造消息

post,postAtTime,postDelayed,postAtFrontOfQueue方法用来发送Runnable对象

sendMessage,sendEmptyMessage,sendEmptyMessageDelayed,sendEmptyMessageAtTime,sendMessageAtFrontOfQueue方法用来发送消息

removeCallbacks,removeMessages方法删除回调

hasMessage,hasCallbacks方法判断是否由回调

getLooper获取Looper

内部类MessengerImpl实现了IMessenger接口,send方法发送该消息,并设置发送者UID

方法getImessenger返回内部类MessengerImpl

 

 

 

 

 

HandlerThread类方便Handler类与Thread绑定,降低了创建和使用带消息队列的线程的难度(是创建Looper,有了Looper自动创建MessgeQueue),Looper是与线程绑定的,最终还是要在一个相关的线程里创建。HandlerThread类会自动添加同步代码将创建Looper与获取Looper同步,直到创建了一个Looper才会返回这个Looper,不会返回一个空的Looper。在外围先start这个HandlerThread,再获取Looper并将返回的Looper传给相应的Handler类绑定即可

 

 

MessageQueue:

MessageQueue维护消息队列,与Native world的MessageQueue由紧密联系

类内部实现了两个Interface,一个静态内部类。

接口IdleHandler在消息队列没有消息时使用,处理poll状态时的动作

接口OnFileDescriptorEventListener在相应的文件状态改变(可读,可写,有错误)时被使用

静态内部类FileDescriptorRecord,记录相应文件状态改变时的监视器OnFileDescriptorEventListener,在被native方法调用的dispatchEvents方法里被调用,执行监视器

 

有个重要的判断是needWake

主要API如下

enqueueMessage:消息进入队列

hasMessages:队列中是否有该消息

removeMessages,removeCallbacksAndMessages,removeAllMessagesLocked,removeAllFutrueMessagesLocked:移除消息

postSyncBarrier/removeSyncBarrier:添加/移除同步屏障,即target为空的消息,next方法会block在这里

next:得到下一条消息

addIdleHandler/removeIdleHandler:添加/删除消息队列为空时的处理类

isIdle:消息队列是否为空

isPolling:是否在轮询

addOnFileDescriptorEventListener/removeOnFileDescriptorEventListener:添加/删除文件状态变化监视器

 

域mMessages为当前消息队列的头

 

还有个辅助类是Message类,承载消息和参数

 

 

主要代码相关三种case:消息循环,消息分发,消息处理