Android消息机制基于源码解析文档格式.docx
- 文档编号:16650450
- 上传时间:2022-11-25
- 格式:DOCX
- 页数:17
- 大小:53.73KB
Android消息机制基于源码解析文档格式.docx
《Android消息机制基于源码解析文档格式.docx》由会员分享,可在线阅读,更多相关《Android消息机制基于源码解析文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
/**
*Low-levelclassholdingthelistofmessagestobedispatchedbya
*{@linkLooper}.MessagesarenotaddeddirectlytoaMessageQueue,
*butratherthrough{@linkHandler}objectsassociatedwiththeLooper.
*
*YoucanretrievetheMessageQueueforthecurrentthreadwith
*{@linkLooper#myQueue()Looper.myQueue()}.
*/
它是一个低等级的持有Messages集合的类,被Looper分发。
Messages并不是直接加到MessageQueue的,而是通过Handler对象和Looper关联到一起。
我们可以通过Looper.myQueue()方法来检索当前线程的MessageQueue。
4.2Message
在整个消息处理机制中,message又叫task,封装了任务携带的信息和处理该任务的handler。
我们看下这个类的注释
*Definesamessagecontainingadescriptionandarbitrarydataobjectthatcanbe
*senttoa{@linkHandler}.Thisobjectcontainstwoextraintfieldsandan
*extraobjectfieldthatallowyoutonotdoallocationsinmanycases.
*WhiletheconstructorofMessageispublic,thebestwaytoget
*oneoftheseistocall{@link#obtainMessage.obtain()}oroneofthe
*{@linkHandler#obtainMessageHandler.obtainMessage()}methods,whichwillpull
*themfromapoolofrecycledobjects.
这个类定义了一个包含描述和一个任意类型对象的对象,它可以被发送给Handler。
从注释里我们还可以了解到以下几点:
尽管Message有public的默认构造方法,但是你应该通过Message.obtain()来从消息池中获得空消息对象,以节省资源。
如果你的message只需要携带简单的int信息,请优先使用Message.arg1和Message.arg2来传递信息,这比用Bundle更省内存
用message.what来标识信息,以便用不同方式处理message
4.3Looper
/*
*Thisclasscontainsthecoderequiredtosetupandmanageaneventloop
*basedonMessageQueue.APIsthataffectthestateofthequeueshouldbe
*definedonMessageQueueorHandlerratherthanonLooperitself.Forexample,
*idlehandlersandsyncbarriersaredefinedonthequeuewhereaspreparingthe
*thread,looping,andquittingaredefinedonthelooper.
这个类是基于消息队列用来设置和管理事件循环的代码,对队列的改变应该在MessageQueue或Handler上定义,而不是在Looper本身定义,例如空间处理和同步障碍应该在队列上定义,然而准备线程、循环和退出在Looper本身定义,
4.4Handler
*AHandlerallowsyoutosendandprocess{@linkMessage}andRunnable
*objectsassociatedwithathread’s{@linkMessageQueue}.EachHandler
*instanceisassociatedwithasinglethreadandthatthread’smessage
*queue.WhenyoucreateanewHandler,itisboundtothethread/
*messagequeueofthethreadthatiscreatingit–fromthatpointon,
*itwilldelivermessagesandrunnablestothatmessagequeueandexecute
*themastheycomeoutofthemessagequeue.
*
TherearetwomainusesforaHandler:
(1)toschedulemessagesand
*runnablestobeexecutedassomepointinthefuture;
and
(2)toenqueue
*anactiontobeperformedonadifferentthreadthanyourown.
Schedulingmessagesisaccomplishedwiththe
*{@link#post},{@link#postAtTime(Runnable,long)},
*{@link#postDelayed},{@link#sendEmptyMessage},
*{@link#sendMessage},{@link#sendMessageAtTime},and
*{@link#sendMessageDelayed}methods.Thepostversionsallow
*youtoenqueueRunnableobjectstobecalledbythemessagequeuewhen
*theyarereceived;
thesendMessageversionsallowyoutoenqueue
*a{@linkMessage}objectcontainingabundleofdatathatwillbe
*processedbytheHandler’s{@link#handleMessage}method(requiringthat
*youimplementasubclassofHandler).
WhenpostingorsendingtoaHandler,youcaneither
*allowtheitemtobeprocessedassoonasthemessagequeueisready
*todoso,orspecifyadelaybeforeitgetsprocessedorabsolutetimefor
*ittobeprocessed.Thelattertwoallowyoutoimplementtimeouts,
*ticks,andothertiming-basedbehavior.
Whena
*processiscreatedforyourapplication,itsmainthreadisdedicatedto
*runningamessagequeuethattakescareofmanagingthetop-level
*applicationobjects(activities,broadcastreceivers,etc)andanywindows
*theycreate.Youcancreateyourownthreads,andcommunicatebackwith
*themainapplicationthreadthroughaHandler.Thisisdonebycalling
*thesamepostorsendMessagemethodsasbefore,butfrom
*yournewthread.ThegivenRunnableorMessagewillthenbescheduled
*intheHandler’smessagequeueandprocessedwhenappropriate.
这个有点长,简单概括下:
每一个Handler实例关联了一个单一的ghread和这个thread的messagequeue,当Handler的实例被创建的时候它就被绑定到了创建它的thread。
它用来调度message和runnables在未来某个时间点的执行,还可以排列其他线程里执行的操作。
Handler主要用的来管理某个线程(也可能是进程)的消息队列。
比如处理主线程的消息队列,包含消息的发送和接收过程。
消息的发送可以通过Post的一系列方法和Sende的一系列方法来实现。
而post的一系列方法最终是通过send的一系列方法来实现的。
这样就可以将一些耗时任务放到其他线程之中,待任务完成之后就往主线程的消息队列中添加一个消息,这样Handler的Callback,即handleMessage就会被调用。
但是Handler并不是线程安全的,因此建议将Handler作为一个静态内部类。
所以Handler只是处理消息,耗时任务放在其他线程。
4.5四元素的交互过程
具体工作过程
消息队列的创建
消息循环
消息的发送最基本的两个API
带一个Runnable参数,会被转换为一个Message参数
带一个Message参数,用来描述消息的内容
Handler.sendMessage
Handler.post
消息的处理
基于消息的异步任务接口
android.os.HandlerThread
适合用来处于不需要更新UI的后台任务
android.os.AyncTask
适合用来处于需要更新UI的后台任务
4.5.1Looper与消息队列的创建
首先确认当前线程是否具有Looper(主线程默认具有Looper)如果没有则创建
我们知道Android上一个应用的入口,应该是ActivityThread。
和普通的Java类一样,入口是一个main方法。
创建主线程源码示例:
publicstaticvoidmain(String[]args){
//~省略部分无关代码~
//创建Looper和MessageQueue对象,用于处理主线程的消息
Looper.prepareMainLooper();
//创建ActivityThread对象
ActivityThreadthread=newActivityThread();
//建立Binder通道(创建新线程)
thread.attach(false);
if(sMainThreadHandler==null){
sMainThreadHandler=thread.getHandler();
}
if(false){
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG,"
ActivityThread"
));
//EndofeventActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//消息循环运行
Looper.loop();
thrownewRuntimeException("
Mainthreadloopunexpectedlyexited"
);
}
我们可以看到主方法首先通过Looper.prepareMainLooper()初始化了我们主线程(UI)的Looper并且启动它。
然后就可以处理子线程和其他组件发来的消息了
如果不是主线程的两线程进行通信,可以通过以下方式来创建
classLooperThreadextendsThread{
publicHandlermHandler;
publicvoidrun(){
//将当前线程初始化为Looper线程
Looper.prepare();
//...其他处理,如实例化handler
mHandler=newHandler(){
publicvoidhandleMessage(Messagemsg){
//processincomingmessageshere
};
//开始循环处理消息队列
Looper源码如下:
publicfinalclassLooper{
privatestaticfinalStringTAG="
Looper"
;
//sThreadLocal.get()willreturnnullunlessyou'
vecalledprepare().
staticfinalThreadLocal<
Looper>
sThreadLocal=newThreadLocal<
();
privatestaticLoopersMainLooper;
//guardedbyLooper.class
//Looper内的消息队列
finalMessageQueuemQueue;
//当前线程
finalThreadmThread;
privatePrintermLogging;
privateLooper(booleanquitAllowed){
mQueue=newMessageQueue(quitAllowed);
mThread=Thread.currentThread();
/**Initializethecurrentthreadasalooper.
*Thisgivesyouachancetocreatehandlersthatthenreference
*thislooper,beforeactuallystartingtheloop.Besuretocall
*{@link#loop()}aftercallingthismethod,andenditbycalling
*{@link#quit()}.
*/
publicstaticvoidprepare(){
prepare(true);
privatestaticvoidprepare(booleanquitAllowed){
//试图在有Looper的线程中再次创建Looper将抛出异常
if(sThreadLocal.get()!
=null){
OnlyoneLoopermaybecreatedperthread"
sThreadLocal.set(newLooper(quitAllowed));
/**
*Initializethecurrentthreadasalooper,markingitasan
*application'
smainlooper.Themainlooperforyourapplication
*iscreatedbytheAndroidenvironment,soyoushouldneverneed
*tocallthisfunctionyourself.Seealso:
{@link#prepare()}
publicstaticvoidprepareMainLooper(){
prepare(false);
synchronized(Looper.class){
if(sMainLooper!
thrownewIllegalStateException("
ThemainLooperhasalreadybeenprepared."
sMainLooper=myLooper();
从中我们可以看到以下几点:
prepare()其核心就是将looper对象定义为ThreadLocal
一个Thread只能有一个Looper对象
prepare()方法会调用Looper的构造方法,初始化一个消息队列,并且指定当前线程
ThreadLocal并不是一个Thread,而是Thread的局部变量。
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本。
所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。
在调用Looper.loop()方法之前,确保已经调用了prepare(booleanquitAllowed)方法,并且我们可以调用quite方法结束循环
接下来再看看Looper.loop()
/**
*Runthemessagequeueinthisthread.Besuretocall
*{@link#quit()}toendtheloop.
publicstaticvoidloop(){
//得到当前线程Looper
finalLooperme=myLooper();
if(me==null){
NoLooper;
Looper.prepare()wasn'
tcalledonthisthread."
//得到当前looper的MessageQueue
finalMessageQueuequeue=me.mQueue;
//Makesuretheidentityofthisthreadisthatofthelocalprocess,
//andkeeptrackofwhatthatidentitytokenactuallyis.
Binder.clearCallingIdentity();
finallongident=Binder.clearCallingIdentity();
//开始循环
for(;
){
Messagemsg=queue.next();
//mightblock
if(msg==null){
//Nomessageindicatesthatthemessagequeueisquitting.
//没有消息表示消息队列正在退出
return;
//Thismustbeinalocalvariable,incaseaUIeventsetsthelogger
Printerlogging=me.mLogging;
if(logging!
logging.println("
>
Dispatchingto"
+msg.target+"
"
+
msg.callback+"
:
+msg.what);
//将真正的处理工作交给message的target,即handler
msg.target.dispatchMessage(msg);
<
Finishedto"
+msg.callback);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 消息 机制 基于 源码 解析