Android消息机制之HandlerMessageQueueLooper源码剖析Word格式.docx
- 文档编号:20462965
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:70
- 大小:40.08KB
Android消息机制之HandlerMessageQueueLooper源码剖析Word格式.docx
《Android消息机制之HandlerMessageQueueLooper源码剖析Word格式.docx》由会员分享,可在线阅读,更多相关《Android消息机制之HandlerMessageQueueLooper源码剖析Word格式.docx(70页珍藏版)》请在冰豆网上搜索。
消息存放者,存放了一个消息队列,有消息进来的时候安插在指定的位置,需要处理的时候将消息取出来。
消息排队者,将消息按处理的时间进行存放,让消息排队进行处理。
Looper:
运行机制全局掌控者,让整个机制活动起来的关键人员,将所有角色联系起来,根据具体实现进行调度,完成整个机制的任务。
部持有一个MessageQueue,
Handler通过关联Looper,联系上MessageQueue。
大体的运转结构
了解了这些类在整个任务中充当的角色何彼此之间的联系之后,我们来看看他们大体都做了些什么工作,让整个机制运转起来。
Handler通过sendMessage方法,将Message发送出去,MessageQueue通过queueMessage方法将消息存插入到消息队列中等待被处理。
Looper通过loop方法在特定的时间到MessageQueue中将消息取出来,回调Handler的dispatchMessage方法将消息交给Handler处理。
具体为什么就将数据在线程之间传递成功了呢?
通过第2点,我们大体了解了整个机制的原理,但是这样做为什么就能实现线程间数据的传递呢?
这个问题很关键,在我们源代码分析完了之后再来进行讲解,这儿先不说。
源代码剖析:
下面我们对源代码进行剖析,然后再来看看上面提到的理论和问题,整个消息机制就完全理解掌握了!
Handler源码分析:
publicclassHandler{
privatestaticfinalbooleanFIND_POTENTIAL_LEAKS=false;
privatestaticfinalStringTAG="
Handler"
;
//当前handler所在线程的looper
finalLoopermLooper;
//跟looper对应的消息队列
finalMessageQueuemQueue;
//处理消息的回调
finalCallbackmCallback;
//决定处理消息的方式同步的还是异步的
finalbooleanmAsynchronous;
IMessengermMessenger;
/**
*通过设置这个接口去处理消息,就不需要再定义一个Handler的子类
*/
publicinterfaceCallback{
publicbooleanhandleMessage(Messagemsg);
}
*Subclassesmustimplementthistoreceivemessages.
*Message和Handler都没有callback才会调用处理消息,这儿啥也没做,留着口给子类去完成了
publicvoidhandleMessage(Messagemsg){
*处理系统消息
*Handlesystemmessageshere.
publicvoiddispatchMessage(Messagemsg){
//如果msg有回调就交给msg处理
if(msg.callback!
=null){
handleCallback(msg);
}else{
//msg没有回调,创建Handler的时候有给回调就交给这个回调处理
if(mCallback!
if(mCallback.handleMessage(msg)){
return;
//调用自己的handleMessage方法处理,什么也没做,交给子类去具体实现,具体操作。
平时我们用的匿名部类的方式就是走了这一步
handleMessage(msg);
publicHandler(){
this(null,false);
*构造方法,设定消息处理回调,如果当前线程中没有Looper的时候,将接不到消息,还会抛出异常
publicHandler(Callbackcallback){
this(callback,false);
*构造方法,指定一个Looper,用这个Looper替换默认的Looper
publicHandler(Looperlooper){
this(looper,null,false);
publicHandler(Looperlooper,Callbackcallback){
this(looper,callback,false);
*设定当前Handler是同步处理消息还是异步处理消息
publicHandler(booleanasync){
this(null,async);
*构造方法,初始化
publicHandler(Callbackcallback,booleanasync){
if(FIND_POTENTIAL_LEAKS){
finalClass<
?
extendsHandler>
klass=getClass();
if((klass.isAnonymousClass()||klass.isMemberClass()||klass.isLocalClass())&
&
(klass.getModifiers()&
Modifier.STATIC)==0){
Log.w(TAG,"
ThefollowingHandlerclassshouldbestaticorleaksmightoccur:
"
+
klass.getCanonicalName());
//获取一个Looper,UI线程系统自动调用prepareMainLooper方法,创建了UI线程的looper
//如果Handler在子线程中创建,必须先调用prepare创建一个looper,否则myLooper返回的是null,会抛出异常
mLooper=Looper.myLooper();
if(mLooper==null){
thrownewRuntimeException(
Can'
tcreatehandlerinsidethreadthathasnotcalledLooper.prepare()"
);
//
mQueue=mLooper.mQueue;
mCallback=callback;
mAsynchronous=async;
*构造方法,初始化。
跟2个参数的构造方法的区别是,这儿直接给定了looper
publicHandler(Looperlooper,Callbackcallback,booleanasync){
mLooper=looper;
mQueue=looper.mQueue;
*获取trace文件的名字,ANR分析的时候有用
publicStringgetTraceName(Messagemessage){
finalStringBuildersb=newStringBuilder();
sb.append(getClass().getName()).append("
:
if(message.callback!
sb.append(message.callback.getClass().getName());
sb.append("
#"
).append(message.what);
returnsb.toString();
*获取消息的名称,用消息的callback类名或者what的十六进制命名
*
*parammessageThemessagewhosenameisbeingqueried
publicStringgetMessageName(Messagemessage){
//如果规定了message的回调,返回该回调类的名字
returnmessage.callback.getClass().getName();
//如果message没有指定回调,返回what的十六进制
return"
0x"
+Integer.toHexString(message.what);
*从消息池中获取一个回收的message对象返回,
*但是这个message的处理handler是调用该方法的handler
*这样效率比直接new一个Message要好
*如果不想处理消息的handler被指定为调用的handler可以调用Message.obtain方法
publicfinalMessageobtainMessage(){
returnMessage.obtain(this);
*跟上面的方法差不多,只是多了一点,指定了message的what变量值
publicfinalMessageobtainMessage(intwhat){
returnMessage.obtain(this,what);
publicfinalMessageobtainMessage(intwhat,Objectobj){
returnMessage.obtain(this,what,obj);
publicfinalMessageobtainMessage(intwhat,intarg1,intarg2){
returnMessage.obtain(this,what,arg1,arg2);
publicfinalMessageobtainMessage(intwhat,intarg1,intarg2,Objectobj){
returnMessage.obtain(this,what,arg1,arg2,obj);
*将一个Runnable放到消息队列中,处理的时候是由当前handler依附的线程处理
publicfinalbooleanpost(Runnabler){
returnsendMessageDelayed(getPostMessage(r),0);
*跟上面的方法一样,只是多了一个执行的时间指定,会在(uptimeMillis)这段时间过后才执行
publicfinalbooleanpostAtTime(Runnabler,longuptimeMillis){
returnsendMessageAtTime(getPostMessage(r),uptimeMillis);
publicfinalbooleanpostAtTime(Runnabler,Objecttoken,longuptimeMillis){
returnsendMessageAtTime(getPostMessage(r,token),uptimeMillis);
publicfinalbooleanpostDelayed(Runnabler,longdelayMillis){
returnsendMessageDelayed(getPostMessage(r),delayMillis);
publicfinalbooleanpostAtFrontOfQueue(Runnabler){
returnsendMessageAtFrontOfQueue(getPostMessage(r));
publicfinalbooleanrunWithScissors(finalRunnabler,longtimeout){
if(r==null){
thrownewIllegalArgumentException("
runnablemustnotbenull"
if(timeout<
0){
timeoutmustbenon-negative"
if(Looper.myLooper()==mLooper){
r.run();
returntrue;
BlockingRunnablebr=newBlockingRunnable(r);
returnbr.postAndWait(this,timeout);
*移除消息队列中所有待处理的任务
publicfinalvoidremoveCallbacks(Runnabler){
mQueue.removeMessages(this,r,null);
*RemoveanypendingpostsofRunnable<
var>
r<
/var>
withObject
*<
token<
thatareinthemessagequeue.If<
isnull,
*allcallbackswillberemoved.
publicfinalvoidremoveCallbacks(Runnabler,Objecttoken){
mQueue.removeMessages(this,r,token);
*将消息push到消息队列的队尾,轮到处理该消息的时候会回调handleMessage去处理
*如果push成功返回true,如果这个消息队列已经exiting,将会push失败,返回false
publicfinalbooleansendMessage(Messagemsg){
returnsendMessageDelayed(msg,0);
*将一个没有携带数据,只有what值的空消息push到消息队列中
publicfinalbooleansendEmptyMessage(intwhat){
returnsendEmptyMessageDelayed(what,0);
*将一个没有携带数据,只有what值的空消息push到消息队列中,但是会在特定的时间过后才能被delivered
publicfinalbooleansendEmptyMessageDelayed(intwhat,longdelayMillis){
Messagemsg=Message.obtain();
msg.what=what;
returnsendMessageDelayed(msg,delayMillis);
publicfinalbooleansendEmptyMessageAtTime(intwhat,longuptimeMillis){
returnsendMessageAtTime(msg,uptimeMillis);
*将一个消息放入队列,在当前时间+delayMillis(比如:
一个小时之后处理,现在是12点,那就是12:
00+1*60*60*1000)
*时间点之前应该要处理的消息全部处理完了之后,会在当前handler依附的线程中处理该消息。
*这个消息将被传到handleMessage方法中
publicfinalbooleansendMessageDelayed(Messagemsg,longdelayMillis){
if(delayMillis<
delayMillis=0;
returnsendMessageAtTime(msg,SystemClock.uptimeMillis()+delayMillis);
*将一个消息放入消息队列,在uptimeMillis(比如13:
00)这个绝对时间点之前应该处理的消息处理完成之后会处理该消息
publicbooleansendMessageAtTime(Messagemsg,longuptimeMillis){
MessageQueuequeue=mQueue;
if(queue==null){
RuntimeExceptione=newRuntimeException(
this+"
sendMessageAtTime()calledwithnomQueue"
Log.w("
Looper"
e.getMessage(),e);
returnfalse;
returnenqueueMessage(queue,msg,uptimeMillis);
*讲一个消息放在队首,这个方法一般不会使用,需要在特定的情况下使用。
因为这个方法可能会导致
*消息队列的排序出现问题,或者一些无法想象的异常出现
publicfinalbooleansendMessageAtFrontOfQueue(Messagemsg){
returnenqueueMessage(queue,msg,0);
*将消息放入队列中,在uptimeMillis(13:
00)处理这个消息
*paramqueue将消息放入这个消息队列
*parammsg想要处理的消息
*paramuptimeMillis处理的绝对时间点
*return
privatebooleanenqueueMessage(MessageQueuequeue,Messagemsg,longuptimeMillis){
//指定处理该消息的handler为当前调用的handler
msg.target=this;
if(mAsynchronous){
//将消息设置为可异步
msg.setAsynchronous(true);
returnqueue.enqueueMessage(msg,uptimeMillis);
*从消息队列中移除指定what值的,未处理的消息.移除之后这些消息对象会被回收,将不会被取出执行
publicfinalvoidremoveMessages(intwhat){
mQueue.removeMessages(this,what,null);
*从消息队列中移除指定what,和obj值,并且未处理的消息,移除之后这些消息对象会被回收,将不会被取出执行
publicfinalvoidremoveMessages(intwhat,Objectobject){
mQueue.removeMessages(this,what,object);
*从消息队列中移除所有指定obj值,并且未处理的消息和任务,移除之后这些消息对象会被回收,将不会被取出执行
publicfinalvoidremoveCallbacksAndMessages(Objecttoken){
mQueue.removeCallbacksAndMessages(this,token);
*查询消息队列中是否有跟指定what值的消息
public
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 消息 机制 HandlerMessageQueueLooper 源码 剖析
链接地址:https://www.bdocx.com/doc/20462965.html