您的位置:首页 > 移动开发 > Android开发

Android消息机制之一---Looper

2016-03-03 09:01 295 查看
1.1Looper

位置:

/frameworks/base/core/java/android/os/Looper.java

Looper:循环者的意思,他被设计用来将一个普通线程变成Looper线程,即循环工作的线程。
/*
56*APIImplementationNote:
57*
58*Thisclasscontainsthecoderequiredtosetupandmanageaneventloop
59
*basedonMessageQueue.APIsthataffectthestateofthequeueshouldbe
60
*definedonMessageQueueorHandlerratherthanonLooperitself.Forexample,
61
*idlehandlersandsyncbarriersaredefinedonthequeuewhereaspreparingthe
62
*thread,looping,andquittingaredefinedonthelooper.
63
*/

Looper类基于MessageQueue(消息队列)来管理一个循环事件。并且这个消息队列的状态是在MessageQueue(消息队列)或者Handler中设置和更改的,并不是在Looper中。也就是说,Looper通过一个由其他类控制的MessageQueue来维持循环。其中MessageQueue已经封装到了Looper中,对于开发者来说,MessageQueue是透明的,直接操作的是Message。

如何是一个正常的线程变成Looper线程:

publicclassLooperThreadextendsThread{

@Override

publicvoidrun(){

//将当前线程初始化为Looper线程

Looper.prepare();

//...其他处理,如实例化handler

//开始循环处理消息队列

Looper.loop();

}

}

通过两行核心代码,普通线程就会变成Looper线程。

Looper.prepare()

Looper.loop()



通过Looper.prepare(),线程中就会出现一个Looper的对象,它内部维护一个消息队列,并且通过prepare()源码我们发现,一个线程只能对应一个Looper对象。

其实,将普通线程,变成Looper线程比较简单。接下来,我们看下Looper的源码,分析下它的实现。

//sThreadLocal.get()willreturnnullunlessyou'vecalledprepare().

68staticfinalThreadLocal<Looper>sThreadLocal=newThreadLocal<Looper>();//每个线程只能有一个Looper对象

69privatestaticLoopersMainLooper;//guardedbyLooper.class

70

71finalMessageQueuemQueue;//消息队列

72finalThreadmThread;//当前线程

73

74privatePrintermLogging;


每个线程中的Looper对象其实就是一个ThreadLocal,即线程本地存储(TLS)对象。

/**Initializethecurrentthreadasalooper.

77*Thisgivesyouachancetocreatehandlersthatthenreference

78*thislooper,beforeactuallystartingtheloop.Besuretocall

79*{@link#loop()}aftercallingthismethod,andenditbycalling

80*{@link#quit()}.

81*/

publicstaticvoidprepare(){

prepare(true);

}


//最后会调用该方法;

privatestaticvoidprepare(booleanquitAllowed){

if(sThreadLocal.get()!=null){

thrownewRuntimeException("OnlyoneLoopermaybecreatedperthread");

}

sThreadLocal.set(newLooper(quitAllowed));

}


prepare(BooleanquitAllowed);方法是利用TLS来产生Looper对象。

privateLooper(booleanquitAllowed){

mQueue=newMessageQueue(quitAllowed);

mThread=Thread.currentThread();//Looper的Thread指向的是当前的线程

}


Looper的构造方法。

生成MessageQueue;

mThread指向当前线程;

Looper中的主循环,loop(循环),知道quit()后执行终止loop

/**

*Runthemessagequeueinthisthread.Besuretocall

*{@link#quit()}toendtheloop.

*/

publicstaticvoidloop(){

finalLooperme=myLooper();//得到当前线程Looper

if(me==null){

thrownewRuntimeException("NoLooper;Looper.prepare()wasn'tcalledonthisthread.");

}

//得到当前Looper的MQ(消息队列)

finalMessageQueuequeue=me.mQueue;

//Makesuretheidentityofthisthreadisthatofthe//localprocess,

//andkeeptrackofwhatthatidentitytokenactually//is.

//确定该线程是属于本地进程,不影响Looper理解

Binder.clearCallingIdentity();

finallongident=Binder.clearCallingIdentity();

for(;;){//开始循环

Messagemsg=queue.next();//mightblock

if(msg==null){

//Nomessageindicatesthatthemessagequeueisquitting.

return;

}

//日志内容

//Thismustbeinalocalvariable,incaseaUIeventsetsthelogger

Printerlogging=me.mLogging;

if(logging!=null){

logging.println(">>>>>Dispatchingto"+msg.target+""+msg.callback+":"+msg.what);

}


//重要,真正的处理工作借给Message的target,即handler

msg.target.dispatchMessage(msg);

if(logging!=null){

logging.println("<<<<<Finishedto"+msg.target+""+msg.callback);

}

//ID处理

//Makesurethatduringthecourseofdispatchingthe

//identityofthethreadwasn'tcorrupted.

finallongnewIdent=Binder.clearCallingIdentity();if(ident!=newIdent){

Log.wtf(TAG,"Threadidentitychangedfrom0x"

+Long.toHexString(ident)+"to0x"

+Long.toHexString(newIdent)+"whiledispatchingto"

+msg.target.getClass().getName()+""

+msg.callback+"what="+msg.what);

}

//回收Message资源

msg.recycleUnchecked();

}

}



当Looper调用loop()后,looper线程开始真正的工作。

Looper的其他函数:

myLooper()//获取当前Looper

publicstatic@NullableLoopermyLooper(){

returnsThreadLocal.get();

}

//getMainLooper()获取application中的主线程的looper

/**

*Returnstheapplication'smainlooper,whichlivesinthemainthreadoftheapplication.

*/

publicstaticLoopergetMainLooper(){

synchronized(Looper.class){

returnsMainLooper;

}

}

quit()函数;

//一些消息可能还没有提交,在loop处理结束之前

publicvoidquit(){

mQueue.quit(false);

}

//所有消息都处理结束,并且没有新的消息提交

publicvoidquitSafely(){

mQueue.quit(true);

}

其中android中的Actvity也为一个Looper线程。

Looper循环者,它设计是用来是一个普通线程变成Looper线程。主要作用是使一个线程不断循环,一旦有新任务则完成新任务,之后继续循环等待下一个任务。

总结:

1.每个线程有且最多只能有一个Looper对象,它是一个ThreadLocal

2.Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行

3.Looper使一个线程变成Looper线程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: