这一节来分析Handler的源码实现,Handler从字面理解就是处理程序、处理器的意思,在Android消息机制中它扮演着执行者的角色,消息的发送、接收、处理都是由Handler来完成的,它也是跟开发者打交道最多的,因此我们更有必要深入了解Handler的实现原理。

一、首先是Handler类的定义:

publicclassHandler

Handler有以下几个主要属性字段:

finalMessageQueuemQueue;
finalLoopermLooper;
finalCallbackmCallback;
finalbooleanmAsynchronous;
IMessengermMessenger;

mQueue是一个MessageQueue对象,第一节讲Message的时候提到过,发送的消息会放到一个消息队列里面,就是它了,第四节会详细讲解MessageQueuemLooper是一个Looper对象,可以理解为一个循环器,它不断从消息队列中将消息取出来,交给Handler处理,第三节也会详细分析其实现原理,暂时理解它的作用就行;mCallBackHandler中定义的一个CallBack接口,下文会讲起具体作用;mAsynchronous表示是否为异步处理的布尔值,一般在调用Handler的构造函数时会给其赋值,默认都为false,如果设置为true,其本质会调用第一节中MessagesetAsynchronous(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时不需要开发者自己创建LooperActivityThread已经为我们创建好了,具体源码在ActivityThreadmain()方法中,有兴趣的可以去验证一下。如果在子线程中创建Handler对象,则必须要提供Looper对象,至于Looper怎样创建,在下一节会详细说明。其他参数如CallBack及异步标识async就很好理解了。

三、接下来是HandlerobtainMessage()系列方法:

publicfinalMessageobtainMessage()

publicfinalMessageobtainMessage(intwhat)

publicfinalMessageobtainMessage(intwhat,Objectobj)

publicfinalMessageobtainMessage(intwhat,intarg1,intarg2)

publicfinalMessageobtainMessage(intwhat,intarg1,intarg2,Objectobj)

这一系列方法内部实质上是调用Messageobtain()系列方法,从消息池中获取一个Message,在第一节也提到过。

四、下面是最重要的发送消息环节了,可以利用Handler发送RunnableMessage,且各自对应一系列同名方法,如发送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赋值给了Messagecallback字段,详细代码如下:

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可以发送RunnableMessage,因此它还提供了相关的删除方法:

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》

更多相关文章

  1. Android基于cordova3.3的插件开发
  2. Path相关方法讲解(二)
  3. 基于Android10的Activity的启动流程简析
  4. Android中使用socket使底层和framework通信的实现方法
  5. Android系列之Activity
  6. java版 android遥控电脑关机
  7. Android与WebView的插件管理机制
  8. Android获取ROOT权限的通用方法
  9. [Android] 面试题总结-猎趣-Android部分

随机推荐

  1. Android - 游戏中的声音
  2. 利用python自动清除Android工程中的多余
  3. Android虚拟机上安装apk(adb配置)
  4. 手把手教你:android调用系统相机、相册功
  5. 关于android语言切换后通知栏显示的问题
  6. Android中使用Makefile编译程序和库的方
  7. TextView设置最多显示指定个字符,超过部分
  8. marsboard Android 4.4 添加开机自动设置
  9. Android上下文菜单
  10. 我的android 第37天 -服务--Service(二)