Android消息机制源码解析(二)——消息的执行者Handler
这一节来分析Handler的源码实现,Handler从字面理解就是处理程序、处理器的意思,在Android消息机制中它扮演着执行者的角色,消息的发送、接收、处理都是由Handler来完成的,它也是跟开发者打交道最多的,因此我们更有必要深入了解Handler的实现原理。
一、首先是Handler类的定义:
publicclassHandler
Handler有以下几个主要属性字段:
finalMessageQueuemQueue;
finalLoopermLooper;
finalCallbackmCallback;
finalbooleanmAsynchronous;
IMessengermMessenger;
mQueue是一个MessageQueue对象,第一节讲Message的时候提到过,发送的消息会放到一个消息队列里面,就是它了,第四节会详细讲解MessageQueue;mLooper是一个Looper对象,可以理解为一个循环器,它不断从消息队列中将消息取出来,交给Handler处理,第三节也会详细分析其实现原理,暂时理解它的作用就行;mCallBack是Handler中定义的一个CallBack接口,下文会讲起具体作用;mAsynchronous表示是否为异步处理的布尔值,一般在调用Handler的构造函数时会给其赋值,默认都为false,如果设置为true,其本质会调用第一节中Message的setAsynchronous(boolean)方法,将消息设为异步消息;mMessenger是用来进程间通信的,本文暂不作过多解释。
二、再来看Handler的构造函数,源码中共提供了7个无参或有参的构造函数,罗列如下:
publicHandler()
publicHandler(Callbackcallback)
publicHandler(Looperlooper)
publicHandler(Looperlooper,Callbackcallback)
publicHandler(booleanasync)
publicHandler(Callbackcallback,booleanasync)
publicHandler(Looperlooper,Callbackcallback,booleanasync)
上述几个构造函数,你可以根据需求使用任何一个来创建Handler实例,需要注意的是一个Handler必须要对应一个Looper。一个线程中只能有一个Looper,但可以有多个Handler,虽然有的构造函数没有Looper参数,那是因为在主线程中使用Handler时不需要开发者自己创建Looper,ActivityThread已经为我们创建好了,具体源码在ActivityThread的main()方法中,有兴趣的可以去验证一下。如果在子线程中创建Handler对象,则必须要提供Looper对象,至于Looper怎样创建,在下一节会详细说明。其他参数如CallBack及异步标识async就很好理解了。
三、接下来是Handler的obtainMessage()系列方法:
publicfinalMessageobtainMessage()
publicfinalMessageobtainMessage(intwhat)
publicfinalMessageobtainMessage(intwhat,Objectobj)
publicfinalMessageobtainMessage(intwhat,intarg1,intarg2)
publicfinalMessageobtainMessage(intwhat,intarg1,intarg2,Objectobj)
这一系列方法内部实质上是调用Message的obtain()系列方法,从消息池中获取一个Message,在第一节也提到过。
四、下面是最重要的发送消息环节了,可以利用Handler发送Runnable或Message,且各自对应一系列同名方法,如发送Runnable的方法主要有:
publicfinalbooleanpost(Runnabler)
publicfinalbooleanpostAtTime(Runnabler,longuptimeMillis)
publicfinalbooleanpostAtTime(Runnabler,Objecttoken,longuptimeMillis)
publicfinalbooleanpostDelayed(Runnabler,longdelayMillis)
publicfinalbooleanpostAtFrontOfQueue(Runnabler)
从上述函数名可以很好理解其含义,postAtTime()表示在某个特定时间点发送;postDelayed()表示延迟多久发送消息;postAtFrontOfQueue()表示将消息插入到队列头部。
发送一个Runnable时,实质上会将Runnable转换成一个Message对象。还记得第一节分析Message时的Runnablecallback字段吗?正是通过构造一个Message对象,将所发送的Runnable赋值给了Message的callback字段,详细代码如下:
privatestaticMessagegetPostMessage(Runnabler){
Messagem=Message.obtain();
m.callback=r;
returnm;
}
发送Message的一系列方法为:
publicfinalbooleansendMessage(Messagemsg)
publicfinalbooleansendEmptyMessage(intwhat)
publicfinalbooleansendEmptyMessageDelayed(intwhat,longdelayMillis)
publicfinalbooleansendEmptyMessageAtTime(intwhat,longuptimeMillis)
publicfinalbooleansendMessageDelayed(Messagemsg,longdelayMillis)
publicbooleansendMessageAtTime(Messagemsg,longuptimeMillis)
publicfinalbooleansendMessageAtFrontOfQueue(Messagemsg)
前边几个方法最终会调用到sendMessageAtTime(),来看一下其具体实现:
publicbooleansendMessageAtTime(Messagemsg,longuptimeMillis){
MessageQueuequeue=mQueue;
if(queue==null){
RuntimeExceptione=newRuntimeException(
this+"sendMessageAtTime()calledwithnomQueue");
Log.w("Looper",e.getMessage(),e);
returnfalse;
}
returnenqueueMessage(queue,msg,uptimeMillis);
}
注意到最终调用enqueueMessage(queue,msg,uptimeMillis)方法,顾名思义,就是将该消息添加到队列中。来看下这个方法的具体实现:
privatebooleanenqueueMessage(MessageQueuequeue,Messagemsg,longuptimeMillis){
msg.target=this;
if(mAsynchronous){
msg.setAsynchronous(true);
}
returnqueue.enqueueMessage(msg,uptimeMillis);
}
如果构造Handler时,设置了async参数为true,则会调用消息的msg.setAsynchronous(true)方法,最终的入队操作实际上是在MessageQueue中实现的,第四节会详细分析。
postAtFrontOfQueue(Runnabler)最终会调用sendMessageAtFrontOfQueue(Messagemsg),内部也会调用enqueueMessage(queue,msg,uptimeMillis)方法进行入队操作,只不过uptimeMillis值为0,这样就可以将消息放到队列头部,顺便提一下,这里的uptimeMillis对应着Message里的when字段。
五、既然Handler可以发送Runnable和Message,因此它还提供了相关的删除方法:
publicfinalvoidremoveCallbacks(Runnabler)
publicfinalvoidremoveCallbacks(Runnabler,Objecttoken)
publicfinalvoidremoveMessages(intwhat)
publicfinalvoidremoveMessages(intwhat,Objectobject)
publicfinalvoidremoveCallbacksAndMessages(Objecttoken)
其内部实现都是一样的,都是调用MessageQueue的相关删除方法,将消息从队列中移除,详细内容待第四节分析。
六、消息发送和删除已经分析完了,接下来就是消息接收和处理了,先看相关源码:
/**
*CallbackinterfaceyoucanusewheninstantiatingaHandlertoavoid
*havingtoimplementyourownsubclassofHandler.
*
*@parammsgA{@linkandroid.os.MessageMessage}object
*@returnTrueifnofurtherhandlingisdesired
*/
publicinterfaceCallback{
publicbooleanhandleMessage(Messagemsg);
}
/**
*Subclassesmustimplementthistoreceivemessages.
*/
publicvoidhandleMessage(Messagemsg){
}
/**
*Handlesystemmessageshere.
*/
publicvoiddispatchMessage(Messagemsg){
if(msg.callback!=null){
handleCallback(msg);
}else{
if(mCallback!=null){
if(mCallback.handleMessage(msg)){
return;
}
}
handleMessage(msg);
}
}
第一个是Callback接口的定义,看注释可以知道,在某些情况下如果不想实现Handler的子类,则可以通过实现该接口来处理收到的消息。
第二个是handleMessage(Messagemsg),这个方法是个空方法,需要在子类实现具体的处理逻辑,我们一般多采用这种方法,创建一个Handler子类,通过重写handleMessage(Messagemsg)方法来实现自己的消息处理逻辑,当然上述两种方法都是可以的,看自己的需要了。
第三个是dispatchMessage(Messagemsg)了,也就是消息处理的逻辑。它的执行过程为,如果该消息有callback(也就是之前提到的Runnable对象),则响应callback,具体实现为:
privatestaticvoidhandleCallback(Messagemessage){
message.callback.run();
}
接下来判断是否实现了自定义的Callback接口,如果实现了则响应该接口回调,如果没有,则响应子类的handleMessage(msg)方法。
需要特别注意的是handleMessage(Messagemsg)是在Looper中被调用的,前面简单介绍过,Looper可以理解为消息循环器,作用是不断从MessageQueue中取出消息,交给Handler处理,就是调用了这个方法。因为一个线程只能有一个Looper,如果该Handler是在主线程创建的,那么Looper也是运行在主线程的,同样handleMessage(Messagemsg)也就运行在主线程了,我们常用的使用Handler消息机制更新UI就是这个原理。
Handler的主要内容就是这些,比较容易理解,下一节会继续分析Looper,请关注《Android消息机制源码解析(三)——消息循环器Looper》。
更多相关文章
- Android基于cordova3.3的插件开发
- Path相关方法讲解(二)
- 基于Android10的Activity的启动流程简析
- Android中使用socket使底层和framework通信的实现方法
- Android系列之Activity
- java版 android遥控电脑关机
- Android与WebView的插件管理机制
- Android获取ROOT权限的通用方法
- [Android] 面试题总结-猎趣-Android部分