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

android的消息队列机制

2015-08-18 23:23 447 查看
android下的线程,Looper线程,MessageQueue,Handler,Message等之间的关系,以及Message的send/post及Messagedispatch的过程。


Looper线程

我们知道,线程是进程中某个单一顺序的控制流,它是内核做CPU调度的单位。那何为Looper线程呢?所谓Looper线程,即是借助于Looper和MessageQueue来管理控制流的一类线程。在android系统中,application的主线程即是借助于Looper和MessageQueue来管理控制流的。其实,不仅仅只有主线程可以用Looper和MessageQueue来管理控制流,其他的线程也一样可以。我们可以先看一下android
sourcecode的注释中给出的一种Looper线程的实现方式:

view
source

print?

01
package
com.example.messagequeuedemo;
02
03
import
android.os.Handler;
04
import
android.os.Looper;
05
import
android.util.Log;
06
07
public
class
LooperThread
extends
Thread
{
08
public
static
final
String
TAG=MainActivity.TAG;
09
private
static
final
String
CompTAG=
"<span></span>LooperThread<span></span>"
;
10
11
public
Handler
mHandler;
12
13
@Override
14
public
void
run()
{
15
Log.d(TAG,CompTAG+
":LooperThread=>run"
);
16
Looper.prepare();
17
18
mHandler=
new
Handler()
{
19
public
void
handleMessage(android.os.Message
msg){
20
Log.d(TAG,CompTAG+
":
LooperThread=>Handler=>handleMessage"
);
21
//processincomingmessagehere
22
}
23
};
24
25
Looper.loop();
26
}
27
}
可以看到,就是在线程的run()方法中,调用Looper.prepare()做一些初始化,然后创建一个Handler对象,最后执行Looper.loop()即开始了整个的事件循环。就是这么的简单,一个可以使用消息队列来管理线程执行流程的Looper线程就创建好了。

接着我们来看一下,神秘的Looper.prepare()到底都干了些什么事情:

view
source

print?

01
//sThreadLocal.get()willreturnnullunlessyou'vecalledprepare().
02
static
final
ThreadLocal<Looper>
sThreadLocal=
new
ThreadLocal<Looper>();
03
04
/**Initializethecurrentthreadasalooper.
05
*Thisgivesyouachancetocreatehandlersthatthenreference
06
*thislooper,beforeactuallystartingtheloop.Besure
tocall
07
*{@link#loop()}aftercallingthismethod,andenditby
calling
08
*{@link#quit()}.
09
*/
10
public
static
void
prepare()
{
11
prepare(
true
);
12
}
13
14
private
static
void
prepare(
boolean
quitAllowed)
{
15
if
(sThreadLocal.get()
!=
null
){
16
throw
new
RuntimeException(
"Only
oneLoopermaybecreatedperthread"
);
17
}
18
sThreadLocal.set(
new
Looper(quitAllowed));
19
}
20
21
22
private
Looper(
boolean
quitAllowed)
{
23
mQueue=
new
MessageQueue(quitAllowed);
24
mRun=
true
;
25
mThread=Thread.currentThread();
26
}
可以看到,它做的事情就是为当前的线程创建了一个Looper对象,并存储在一个静态的线程局部变量中。在Looper的构造函数中创建了MessageQueue,同时Looper会引用到当前的线程,并将一个表示状态的变量mRun设置为true。对于此处的线程局部变量sThreadLocal,可以理解为就是一个HashMap,该HashMap中存放的数据其类型为Looper,而HashMap的key则Thread.currentThread()。

启动Looper线程就和启动普通的线程一样,比如:

view
source

print?

01
public
class
MainActivity
extends
Activity
{
02
public
static
final
String
TAG=
"MessageQueueDemo"
;
03
private
static
final
String
CompTAG=
"MainActivity"
;
04
private
LooperThread
mLooperThread;
05
06
@Override
07
protected
void
onCreate(Bundle
savedInstanceState){
08
Log.d(TAG,CompTAG+
":MainActivity=>onCreate"
);
09
super
.onCreate(savedInstanceState);
10
setContentView(R.layout.activity_main);
11
12
mLooperThread=
new
LooperThread();
13
mLooperThread.start();
14
}
同样是new一个Thread对象,然后执行该对象的start()方法。

其实Looper线程有两种,一种就是我们上面看到的那种普通的Looper线程,另外一种则是mainloop线程,创建前者使用我们前面看到的Looper.prepare()方法,而要创建后者,我们则可以使用Looper.prepareMainLooper()方法。可以看一下Looper.prepareMainLooper()的实现:

view
source

print?

01
/**
02
*Initializethecurrentthreadasalooper,markingitas
an
03
*application'smainlooper.Themainlooperforyourapplication
04
*iscreatedbytheAndroidenvironment,soyoushouldnever
need
05
*tocallthisfunctionyourself.Seealso:{@link#prepare()}
06
*/
07
public
static
void
prepareMainLooper()
{
08
prepare(
false
);
09
synchronized
(Looper.
class
)
{
10
if
(sMainLooper
!=
null
){
11
throw
new
IllegalStateException(
"The
mainLooperhasalreadybeenprepared."
);
12
}
13
sMainLooper=myLooper();
14
}
15
}
比较特别的地方即在于,此处调用prepare()方法传进去的参数为false,即表示这个Looper不能够被quit掉。其他倒是基本一样。整个android系统中,调用到prepareMainLooper()方法的大概有两处:

view
source

print?

1
/frameworks/base/services/java/com/android/server/
2
HADSystemServer.java
94
Looper.prepareMainLooper();
3
/frameworks/base/core/java/android/app/
4
HADActivityThread.java
5087
Looper.prepareMainLooper();
一处在ServerThread的run()方法中,用于为systemserver主线程初始化消息队列等,另外一处在ActivityThread的run()方法中,自然即是创建androidapp主线程的消息队列了。


通过消息与Looper线程交互

那Looper线程的特别之处究竟在哪里呢?如前所述,这种线程有一个Looper与之关联,这种线程会使用消息队列,或者称为事件循环来管理执行的流程。那这种特别之处又如何体现呢?其他线程可以向此类线程中丢消息进来,当然此类线程本身也可以往自己的消息队列里面丢消息,然后在事件循环中,这种事件会得到有效的处理。那究竟要如何往Looper线程的消息队列中发送消息呢?

回忆我们前面创建Looper线程的那个code,我们不是有创建出来一个Handler嘛。没错,我们就是通过Handler来向Looper线程的MessageQueue中发送消息的。可以看一下code的写法。先是LooperThread的写法:

view
source

print?

01
package
com.intel.helloworld;
02
03
import
android.os.Handler;
04
import
android.os.Looper;
05
import
android.os.Message;
06
import
android.util.Log;
07
08
public
class
LooperThread
extends
Thread
{
09
private
static
final
String
TAG=MainActivity.TAG;
10
private
static
final
String
CompTAG=
"LooperThread"
;
11
public
Handler
mHandler;
12
13
@Override
14
public
void
run()
{
15
Log.d(TAG,CompTAG+
":"
+
"LooperThread-->run"
);
16
Looper.prepare();
17
18
mHandler=
new
Handler()
{
19
@Override
20
public
void
handleMessage(Message
msg){
21
//processincomingmessage
22
Log.d(TAG,CompTAG+
":
"
+
"Handler-->handleMessage,msg.what="
+
msg.what);
23
}
24
};
25
26
Looper.loop();
27
}
28
29
public
Handler
getHandler(){
30
return
mHandler;
31
}
32
}
然后是向Looper线程发送消息的部分的写法:

view
source

print?

01
package
com.intel.helloworld;
02
03
import
android.os.Bundle;
04
import
android.os.Handler;
05
import
android.os.Message;
06
import
android.app.Activity;
07
import
android.util.Log;
08
import
android.view.Menu;
09
10
public
class
MainActivity
extends
Activity
{
11
public
static
final
String
TAG=
"LifecycleDemoApp"
;
12
private
static
final
String
CompTAG=
"MainActivity"
;
13
14
public
static
final
int
MESSAGE_WHAT_CREATE
=
1
;
15
public
static
final
int
MESSAGE_WHAT_START
=
2
;
16
public
static
final
int
MESSAGE_WHAT_RESUME
=
3
;
17
public
static
final
int
MESSAGE_WHAT_PAUSE
=
4
;
18
public
static
final
int
MESSAGE_WHAT_STOP
=
5
;
19
public
static
final
int
MESSAGE_WHAT_DESTROY
=
6
;
20
21
LooperThreadmThread;
22
23
@Override
24
protected
void
onCreate(Bundle
savedInstanceState){
25
Log.d(TAG,CompTAG+
":"
+
"Activity-->onCreate"
);
26
super
.onCreate(savedInstanceState);
27
setContentView(R.layout.activity_main);
28
29
mThread=
new
LooperThread();
30
mThread.start();
31
}
32
33
@Override
34
protected
void
onStart()
{
35
Log.d(TAG,CompTAG+
":"
+
"Activity-->onStart"
);
36
super
.onStart();
37
38
Handlerhandler=mThread.mHandler;
39
Messagemsg=Message.obtain();
40
msg.what=MESSAGE_WHAT_START;
41
handler.sendMessage(msg);
42
}
43
44
@Override
45
protected
void
onResume()
{
46
Log.d(TAG,CompTAG+
":"
+
"Activity-->onResume"
);
47
super
.onResume();
48
49
Handlerhandler=mThread.mHandler;
50
Messagemsg=Message.obtain();
51
msg.what=MESSAGE_WHAT_RESUME;
52
handler.sendMessage(msg);
53
}
54
55
@Override
56
protected
void
onPause()
{
57
Log.d(TAG,CompTAG+
":"
+
"Activity-->onPause"
);
58
super
.onPause();
59
60
Handlerhandler=mThread.mHandler;
61
Messagemsg=Message.obtain();
62
msg.what=MESSAGE_WHAT_PAUSE;
63
handler.sendMessage(msg);
64
}
65
66
@Override
67
protected
void
onStop()
{
68
Log.d(TAG,CompTAG+
":"
+
"Activity-->onStop"
);
69
super
.onStop();
70
71
Handlerhandler=mThread.mHandler;
72
Messagemsg=Message.obtain();
73
msg.what=MESSAGE_WHAT_STOP;
74
handler.sendMessage(msg);
75
}
76
77
@Override
78
protected
void
onDestroy()
{
79
Log.d(TAG,CompTAG+
":"
+
"Activity-->onDestroy"
);
80
super
.onDestroy();
81
82
Handlerhandler=mThread.mHandler;
83
Messagemsg=Message.obtain();
84
msg.what=MESSAGE_WHAT_DESTROY;
85
handler.sendMessage(msg);
86
}
87
88
@Override
<spanstyle=
"color:
rgb(229,51,51);"
></span>
public
boolean
onCreateOptionsMenu(Menu
menu){
89
//Inflatethemenu;thisaddsitemstotheactionbar
ifitispresent.
90
getMenuInflater().inflate(R.menu.main,menu);
91
return
true
;
92
}
93
94
@Override
95
protected
void
onSaveInstanceState(Bundle
outState){
96
Log.d(TAG,CompTAG+
":"
+
"Activity-->onSaveInstanceState"
);
97
super
.onSaveInstanceState(outState);
98
}
99
}
向一个Looper线程发送消息的过程,基本上即是,调用Message.obtain()或Handler.obtainMessage()获取一个Message对象->设置Message->调用Looper线程中创建的Handler对象来发送消息。

Handler究竟是如何知道要向哪个MessageQueue中发送消息呢,从前面的code中,我们找不到任何将Handler与特定的MessageQueue关联起来的代码,这究竟是怎么回事呢?这也是我们强调要使用Looper线程中创建的Handler对象来向该Looper线程中发送消息的原因。我们可以看一下Handler对象构造的过程:

view
source

print?

001
/**
002
*Defaultconstructorassociatesthishandlerwiththe{@link
Looper}forthe
003
*currentthread.
004
*
005
*Ifthisthreaddoesnothavealooper,thishandlerwon't
beabletoreceivemessages
006
*soanexceptionisthrown.
007
*/
008
public
Handler()
{
009
this
(
null
,
false
);
010
}
011
012
/**
013
*Constructorassociatesthishandlerwiththe{@linkLooper}
forthe
014
*currentthreadandtakesacallbackinterfaceinwhichyou
canhandle
015
*messages.
016
*
017
*Ifthisthreaddoesnothavealooper,thishandlerwon't
beabletoreceivemessages
018
*soanexceptionisthrown.
019
*
020
*@paramcallbackThecallbackinterfaceinwhichtohandle
messages,ornull.
021
*/
022
public
Handler(Callback
callback){
023
this
(callback,
false
);
024
}
025
026
/**
027
*Usetheprovided{@linkLooper}insteadofthedefaultone.
028
*
029
*@paramlooperThelooper,mustnotbenull.
030
*/
031
public
Handler(Looper
looper){
032
this
(looper,
null
,
false
);
033
}
034
035
/**
036
*Usetheprovided{@linkLooper}insteadofthedefaultone
andtakeacallback
037
*interfaceinwhichtohandlemessages.
038
*
039
*@paramlooperThelooper,mustnotbenull.
040
*@paramcallbackThecallbackinterfaceinwhichtohandle
messages,ornull.
041
*/
042
public
Handler(Looper
looper,Callbackcallback){
043
this
(looper,callback,
false
);
044
}
045
046
/**
047
*Usethe{@linkLooper}forthecurrentthread
048
*andsetwhetherthehandlershouldbeasynchronous.
049
*
050
*Handlersaresynchronousbydefaultunlessthisconstructor
isusedtomake
051
*onethatisstrictlyasynchronous.
052
*
053
*Asynchronousmessagesrepresentinterruptsoreventsthat
donotrequireglobalordering
054
*withrepresenttosynchronousmessages.Asynchronousmessages
arenotsubjectto
055
*thesynchronizationbarriersintroducedby{@linkMessageQueue#enqueueSyncBarrier
long)}.
056
*
057
*@paramasyncIftrue,thehandlercalls{@linkMessage#setAsynchronous(boolean)}
for
058
*each{@linkMessage}thatissenttoitor{@linkRunnable}
thatispostedtoit.
059
*
060
*@hide
061
*/
062
public
Handler(
boolean
async)
{
063
this
(
null
,
async);
064
}
065
066
/**
067
*Usethe{@linkLooper}forthecurrentthreadwiththespecified
callbackinterface
068
*andsetwhetherthehandlershouldbeasynchronous.
069
*
070
*Handlersaresynchronousbydefaultunlessthisconstructor
isusedtomake
071
*onethatisstrictlyasynchronous.
072
*
073
*Asynchronousmessagesrepresentinterruptsoreventsthat
donotrequireglobalordering
074
*withrepresenttosynchronousmessages.Asynchronousmessages
arenotsubjectto
075
*thesynchronizationbarriersintroducedby{@linkMessageQueue#enqueueSyncBarrier
long)}.
076
*
077
*@paramcallbackThecallbackinterfaceinwhichtohandle
messages,ornull.
078
*@paramasyncIftrue,thehandlercalls{@linkMessage#setAsynchronous(boolean)}
for
079
*each{@linkMessage}thatissenttoitor{@linkRunnable}
thatispostedtoit.
080
*
081
*@hide
082
*/
083
public
Handler(Callback
callback,
boolean
async){
084
if
(FIND_POTENTIAL_LEAKS)
{
085
final
Class<?
extends
Handler>
klass=getClass();
086
if
((klass.isAnonymousClass()
||klass.isMemberClass()||klass.isLocalClass())&&
087
(klass.getModifiers()&Modifier.STATIC)==
0
)
{
088
Log.w(TAG,
"Thefollowing
Handlerclassshouldbestaticorleaksmightoccur:"
+
089
klass.getCanonicalName());
090
}
091
}
092
093
mLooper=Looper.myLooper();
094
if
(mLooper
==
null
){
095
throw
new
RuntimeException(
096
"Can'tcreatehandlerinsidethreadthathasnotcalled
Looper.prepare()"
);
097
}
098
mQueue=mLooper.mQueue;
099
mCallback=callback;
100
mAsynchronous=async;
101
}
可以看到,很简单,是通过Looper.myLooper()获取到当前线程的Looper对象,并与相关的MessageQueue等关联起来的。这也是前面我们在实现Looper线程时,要在其run方法中创建一个public的Handler的依据。当然,我们也可以在构造Handler对象时,显式地使其与特定的Looper对象关联起来。

Handler提供了两组函数用于向一个Looper线程的MessageQueue中发送消息,分别是postXXX()族和sendXXX()族。可以先看一下sendXXX()族的实现:

view
source

print?

001
/**
002
*Pushesamessageontotheendofthemessagequeueafter
allpendingmessages
003
*beforethecurrenttime.Itwillbereceivedin{@link#handleMessage},
004
*inthethreadattachedtothishandler.
005
*
006
*@returnReturnstrueifthemessagewassuccessfullyplaced
intothe
007
*messagequeue.Returnsfalseonfailure,usually
becausethe
008
*looperprocessingthemessagequeueisexiting.
009
*/
010
public
final
boolean
sendMessage(Message
msg)
011
{
012
return
sendMessageDelayed(msg,
0
);
013
}
014
015
/**
016
*SendsaMessagecontainingonlythewhatvalue.
017
*
018
*@returnReturnstrueifthemessagewassuccessfullyplaced
intothe
019
*messagequeue.Returnsfalseonfailure,usually
becausethe
020
*looperprocessingthemessagequeueisexiting.
021
*/
022
public
final
boolean
sendEmptyMessage(
int
what)
023
{
024
return
sendEmptyMessageDelayed(what,
0
);
025
}
026
027
/**
028
*SendsaMessagecontainingonlythewhatvalue,tobedelivered
029
*afterthespecifiedamountoftimeelapses.
030
*@see#sendMessageDelayed(android.os.Message,long)
031
*
032
*@returnReturnstrueifthemessagewassuccessfullyplaced
intothe
033
*messagequeue.Returnsfalseonfailure,usually
becausethe
034
*looperprocessingthemessagequeueisexiting.
035
*/
036
public
final
boolean
sendEmptyMessageDelayed(
int
what,
long
delayMillis)
{
037
Messagemsg=Message.obtain();
038
msg.what=what;
039
return
sendMessageDelayed(msg,
delayMillis);
040
}
041
042
/**
043
*SendsaMessagecontainingonlythewhatvalue,tobedelivered
044
*ataspecifictime.
045
*@see#sendMessageAtTime(android.os.Message,long)
046
*
047
*@returnReturnstrueifthemessagewassuccessfullyplaced
intothe
048
*messagequeue.Returnsfalseonfailure,usually
becausethe
049
*looperprocessingthemessagequeueisexiting.
050
*/
051
052
public
final
boolean
sendEmptyMessageAtTime(
int
what,
long
uptimeMillis)
{
053
Messagemsg=Message.obtain();
054
msg.what=what;
055
return
sendMessageAtTime(msg,
uptimeMillis);
056
}
057
058
/**
059
*Enqueueamessageintothemessagequeueafterallpending
messages
060
*before(currenttime+delayMillis).Youwillreceiveit
in
061
*{@link#handleMessage},inthethreadattachedtothishandler.
062
*
063
*@returnReturnstrueifthemessagewassuccessfullyplaced
intothe
064
*messagequeue.Returnsfalseonfailure,usually
becausethe
065
*looperprocessingthemessagequeueisexiting.
Notethata
066
*resultoftruedoesnotmeanthemessagewillbe
processed--if
067
*thelooperisquitbeforethedeliverytimeofthe
message
068
*occursthenthemessagewillbedropped.
069
*/
070
public
final
boolean
sendMessageDelayed(Message
msg,
long
delayMillis)
071
{
072
if
(delayMillis
<
0
){
073
delayMillis=
0
;
074
}
075
return
sendMessageAtTime(msg,
SystemClock.uptimeMillis()+delayMillis);
076
}
077
078
/**
079
*Enqueueamessageintothemessagequeueafterallpending
messages
080
*beforetheabsolutetime(inmilliseconds)<var>uptimeMillis</var>.
081
*<b>Thetime-baseis{@linkandroid.os.SystemClock#uptimeMillis}.</b>
082
*Youwillreceiveitin{@link#handleMessage},inthethread
attached
083
*tothishandler.
084
*
085
*@paramuptimeMillisTheabsolutetimeatwhichthemessage
shouldbe
086
*delivered,usingthe
087
*{@linkandroid.os.SystemClock#uptimeMillis}time-base.
088
*
089
*@returnReturnstrueifthemessagewassuccessfullyplaced
intothe
090
*messagequeue.Returnsfalseonfailure,usually
becausethe
091
*looperprocessingthemessagequeueisexiting.
Notethata
092
*resultoftruedoesnotmeanthemessagewillbe
processed--if
093
*thelooperisquitbeforethedeliverytimeofthe
message
094
*occursthenthemessagewillbedropped.
095
*/
096
public
boolean
sendMessageAtTime(Message
msg,
long
uptimeMillis){
097
MessageQueuequeue=mQueue;
098
if
(queue
==
null
){
099
RuntimeExceptione=
new
RuntimeException(
100
this
+
"
sendMessageAtTime()calledwithnomQueue"
);
101
Log.w(
"Looper"
,
e.getMessage(),e);
102
return
false
;
103
}
104
return
enqueueMessage(queue,
msg,uptimeMillis);
105
}
106
107
/**
108
*Enqueueamessageatthefrontofthemessagequeue,to
beprocessedon
109
*thenextiterationofthemessageloop.Youwillreceive
itin
110
*{@link#handleMessage},inthethreadattachedtothishandler.
111
*<b>Thismethodisonlyforuseinveryspecialcircumstances
--it
112
*caneasilystarvethemessagequeue,causeorderingproblems,
orhave
113
*otherunexpectedside-effects.</b>
114
*
115
*@returnReturnstrueifthemessagewassuccessfullyplaced
intothe
116
*messagequeue.Returnsfalseonfailure,usually
becausethe
117
*looperprocessingthemessagequeueisexiting.
118
*/
119
public
final
boolean
sendMessageAtFrontOfQueue(Message
msg){
120
MessageQueuequeue=mQueue;
121
if
(queue
==
null
){
122
RuntimeExceptione=
new
RuntimeException(
123
this
+
"
sendMessageAtTime()calledwithnomQueue"
);
124
Log.w(
"Looper"
,
e.getMessage(),e);
125
return
false
;
126
}
127
return
enqueueMessage(queue,
msg,
0
);
128
}
129
130
private
boolean
enqueueMessage(MessageQueue
queue,Messagemsg,
long
uptimeMillis){
131
msg.target=
this
;
132
if
(mAsynchronous)
{
133
msg.setAsynchronous(
true
);
134
}
135
return
queue.enqueueMessage(msg,
uptimeMillis);
136
}
绕来绕去,最终都是调用MessageQueue的enqueueMessage()方法来将一个Message放入一个MessageQueue中。值得注意的是,在Handler.enqueueMessage()中,会将Message的target设置为this,这实际上是决定了Looper的消息循环中,在dispatch/handlemessage时将会使用的Handler。即,在default情况下,处理message的那个handler也将会是发送此message的handler。

Handler实际的职责,并不像它的名称所显示的那样,其实它不仅仅是处理message,它还负责发送Message给线程的MessageQueue。

再来看一下MessageQueue的enqueueMessage()方法的code:

view
source

print?

01
boolean
enqueueMessage(Message
msg,
long
when){
02
if
(msg.isInUse())
{
03
throw
new
AndroidRuntimeException(msg
+
"Thismessageisalreadyinuse."
);
04
}
05
if
(msg.target
==
null
){
06
throw
new
AndroidRuntimeException(
"Message
musthaveatarget."
);
07
}
08
09
boolean
needWake;
10
synchronized
(
this
)
{
11
if
(mQuiting)
{
12
RuntimeExceptione=
new
RuntimeException(
13
msg.target+
"
sendingmessagetoaHandleronadeadthread"
);
14
Log.w(
"MessageQueue"
,
e.getMessage(),e);
15
return
false
;
16
}
17
18
msg.when=when;
19
Messagep=mMessages;
20
if
(p
==
null
||when==
0
||
when<p.when){
21
//Newhead,wakeuptheeventqueueifblocked.
22
msg.next=p;
23
mMessages=msg;
24
needWake=mBlocked;
25
}
else
{
26
//Insertedwithinthemiddleofthequeue.Usually
wedon'thavetowake
27
//uptheeventqueueunlessthereisabarrierat
theheadofthequeue
28
//andthemessageistheearliestasynchronousmessage
inthequeue.
29
needWake=mBlocked&&p.target==
null
&&
msg.isAsynchronous();
30
Messageprev;
31
for
(;;)
{
32
prev=p;
33
p=p.next;
34
if
(p
==
null
||when<p.when){
35
break
;
36
}
37
if
(needWake
&&p.isAsynchronous()){
38
needWake=
false
;
39
}
40
}
41
msg.next=p;
//invariant:
p==prev.next
42
prev.next=msg;
43
}
44
}
45
if
(needWake)
{
46
nativeWake(mPtr);
47
}
48
return
true
;
49
}
整个将Message放入MessageQueue的算法也还算比较清晰简洁,并没有什么太绕的地方。此处我们可以一览MessageQueue中保存Messages的结构,即,MessageQueue用一个单向链表来保存所有的Message,而链表中各个Message则按照其请求的执行时间先后来排列。

向Looper线程的MessageQueue中发送消息的另外一族方法postXXX(),其实现同前面的sendXXX()族方法也大同小异啦:

view
source

print?

01
/**
02
*CausestheRunnablertobeaddedtothemessagequeue.
03
*Therunnablewillberunonthethreadtowhichthishandler
is
04
*attached.
05
*
06
*@paramrTheRunnablethatwillbeexecuted.
07
*
08
*@returnReturnstrueiftheRunnablewassuccessfullyplaced
intothe
09
*messagequeue.Returnsfalseonfailure,usually
becausethe
10
*looperprocessingthemessagequeueisexiting.
11
*/
12
public
final
boolean
post(Runnable
r)
13
{
14
return
sendMessageDelayed(getPostMessage(r),
0
);
15
}
16
17
private
static
Message
getPostMessage(Runnabler){
18
Messagem=Message.obtain();
19
m.callback=r;
20
return
m;
21
}
Post的message,其callback将是传入的Runnable对象,其他就与send的message一样了。


消息队列中消息的处理

消息队列中的消息是在Looper.loop()中被处理的:

view
source

print?

01
/**
02
*Runthemessagequeueinthisthread.Besuretocall
03
*{@link#quit()}toendtheloop.
04
*/
05
public
static
void
loop()
{
06
final
Looper
me=myLooper();
07
if
(me
==
null
){
08
throw
new
RuntimeException(
"No
Looper;Looper.prepare()wasn'tcalledonthisthread."
);
09
}
10
final
MessageQueue
queue=me.mQueue;
11
12
//Makesuretheidentityofthisthreadisthatofthelocal
process,
13
//andkeeptrackofwhatthatidentitytokenactuallyis.
14
Binder.clearCallingIdentity();
15
final
long
ident
=Binder.clearCallingIdentity();
16
17
for
(;;)
{
18
Messagemsg=queue.next();
//
mightblock
19
if
(msg
==
null
){
20
//Nomessageindicatesthatthemessagequeueisquitting.
21
return
;
22
}
23
24
//Thismustbeinalocalvariable,incaseaUIevent
setsthelogger
25
Printerlogging=me.mLogging;
26
if
(logging
!=
null
){
27
logging.println(
">>>>>
Dispatchingto"
+msg.target+
""
+
28
msg.callback+
":
"
+msg.what);
29
}
30
31
msg.target.dispatchMessage(msg);
32
33
if
(logging
!=
null
){
34
logging.println(
"<<<<<
Finishedto"
+msg.target+
""
+
msg.callback);
35
}
36
37
//Makesurethatduringthecourseofdispatchingthe
38
//identityofthethreadwasn'tcorrupted.
39
final
long
newIdent
=Binder.clearCallingIdentity();
40
if
(ident
!=newIdent){
41
Log.wtf(TAG,
"Thread
identitychangedfrom0x"
42
+Long.toHexString(ident)+
"
to0x"
43
+Long.toHexString(newIdent)+
"
whiledispatchingto"
44
+msg.target.getClass().getName()+
"
"
45
+msg.callback+
"
what="
+msg.what);
46
}
47
48
msg.recycle();
49
}
50
}
这个函数会调用Handler的dispatchMessage()方法来处理消息,其实也就是msg.target对象的dispatchMessage()方法。此外我们可以看到,在Looper.loop()方法的末尾recycle了从MessageQueue中取出的已经dispatch的消息。从而,我们需要通过Handler向一个Looper线程的MessageQueue中发送消息时,我们只要obtain一个Message然后发送就好了,而不需要自己手动去recycle,这些事情将会由Looper来帮助我们完成。接着来看Handler.dispatchMessage()的实现:

view
source

print?

01
/**
02
*Handlesystemmessageshere.
03
*/
04
public
void
dispatchMessage(Message
msg){
05
if
(msg.callback
!=
null
){
06
handleCallback(msg);
07
}
else
{
08
if
(mCallback
!=
null
){
09
if
(mCallback.handleMessage(msg))
{
10
return
;
11
}
12
}
13
handleMessage(msg);
14
}
15
}
在Message的callback成员为非空时,会执行handleCallback(msg),否则的话会依据Handler的mCallback是否为空来确定是否要执行mCallback.handleMessage(msg),并执行Handler的handleMessage(msg)。Handler的handleMessage()方法通常需要override,来实现消息处理的主要逻辑。而mCallback则使得开发者可以比较容易的添加一种对Message做一些额外检测的机制,以提升消息处理的效率。

接着我们看一下,Handler.handleCallback(msg)的实现:

view
source

print?

1
private
static
void
handleCallback(Message
message){
2
message.callback.run();
3
}
很简单的一个方法。可见post的消息的特殊之处,即,此类消息将完全绕过Handler中用于处理消息的handleMessage()方法,而只会执行消息的sender所实现的Runnable。


Sleep-Wakeup机制

还有一个问题,当MessageQueue中没有Messages时,那Looper线程会做什么呢?它会去不停的轮询消息队列中是否有消息吗?计算机科学发展到现在,闭上眼睛我们都能知道,Looper线程将一定不会去轮询的。也确实,android消息队列机制的实现,同样是会在消息队列为空时,让Looper线程去休眠,当消息队列中有了消息之后,再被唤醒。但这样的机制又是如何实现的呢?


Sleep-Wakeup机制所需设施的建立

我们从Sleep-Wakeup机制所需设施的建立开始看起。回忆前面我们看到的Looper的构造函数,它会创建出来一个MessageQueue对象,而Sleep-Wakeup机制所需设施正是在MessageQueue对象的创建过程中创建出来的。我们接着再来看MessageQueue的构造函数:

view
source

print?

1
MessageQueue(
boolean
quitAllowed)
{
2
mQuitAllowed=quitAllowed;
3
mPtr=nativeInit();
4
}
这个方法调用nativeInit()方法来创建出Sleep-Wakeup机制所需设施。我们来看nativeInit()的实现(在frameworks/base/core/jni/android_os_MessageQueue.cpp中):

view
source

print?

01
NativeMessageQueue::NativeMessageQueue():mInCallback(
false
),
mExceptionObj(NULL){
02
mLooper=Looper::getForThread();
03
if
(mLooper
==NULL){
04
mLooper=
new
Looper(
false
);
05
Looper::setForThread(mLooper);
06
}
07
}
08
09
static
jint
android_os_MessageQueue_nativeInit(JNIEnv*env,jclassclazz){
10
NativeMessageQueue*nativeMessageQueue=
new
NativeMessageQueue();
11
if
(!nativeMessageQueue)
{
12
jniThrowRuntimeException(env,
"Unable
toallocatenativequeue"
);
13
return
0;
14
}
15
16
nativeMessageQueue->incStrong(env);
17
return
reinterpret_cast
<jint>(nativeMessageQueue);
18
}
19
20
static
JNINativeMethod
gMessageQueueMethods[]={
21
/*name,signature,funcPtr*/
22
{
"nativeInit"
,
"()I"
,
(
void
*)android_os_MessageQueue_nativeInit},
23
{
"nativeDestroy"
,
"(I)V"
,
(
void
*)android_os_MessageQueue_nativeDestroy},
24
{
"nativePollOnce"
,
"(II)V"
,
(
void
*)android_os_MessageQueue_nativePollOnce},
25
{
"nativeWake"
,
"(I)V"
,
(
void
*)android_os_MessageQueue_nativeWake}
26
};
可以看到,nativeInit()所做的事情,就是创建一个NativeMessageQueue对象,在NativeMessageQueue的构造函数中,会来创建一个Looper对象。与Java层的Looper对象类似,native层的这种Looper对象也是保存在线程局部存储变量中的,每个线程一个。接着我们来看Looper类的构造函数和Looper::getForThread()函数,来了解一下,native层的线程局部存储API的用法(Looper类的实现在frameworks/native/libs/utils/Looper.cpp):

view
source

print?

01
//Hintfornumberoffiledescriptorstobeassociatedwiththeepollinstance.
02
static
const
int
EPOLL_SIZE_HINT
=8;
03
04
//Maximumnumberoffiledescriptorsforwhichtoretrievepolleventseachiteration.
05
static
const
int
EPOLL_MAX_EVENTS
=16;
06
07
static
pthread_once_t
gTLSOnce=PTHREAD_ONCE_INIT;
08
static
pthread_key_t
gTLSKey=0;
09
10
Looper::Looper(
bool
allowNonCallbacks)
:
11
mAllowNonCallbacks(allowNonCallbacks),mSendingMessage(
false
),
12
mResponseIndex(0),mNextMessageUptime(LLONG_MAX){
13
int
wakeFds[2];
14
int
result
=pipe(wakeFds);
15
LOG_ALWAYS_FATAL_IF(result!=0,
"Could
notcreatewakepipe.errno=%d"
,
errno
);
16
17
mWakeReadPipeFd=wakeFds[0];
18
mWakeWritePipeFd=wakeFds[1];
19
20
result=fcntl(mWakeReadPipeFd,F_SETFL,O_NONBLOCK);
21
LOG_ALWAYS_FATAL_IF(result!=0,
"Could
notmakewakereadpipenon-blocking.errno=%d"
,
22
errno
);
23
24
result=fcntl(mWakeWritePipeFd,F_SETFL,O_NONBLOCK);
25
LOG_ALWAYS_FATAL_IF(result!=0,
"Could
notmakewakewritepipenon-blocking.errno=%d"
,
26
errno
);
27
28
//Allocatetheepollinstanceandregisterthewakepipe.
29
mEpollFd=epoll_create(EPOLL_SIZE_HINT);
30
LOG_ALWAYS_FATAL_IF(mEpollFd<0,
"Could
notcreateepollinstance.errno=%d"
,
errno
);
31
32
struct
epoll_event
eventItem;
33
memset
(&eventItem,0,
sizeof
(epoll_event));
//
zerooutunusedmembersofdatafieldunion
34
eventItem.events=EPOLLIN;
35
eventItem.data.fd=mWakeReadPipeFd;
36
result=epoll_ctl(mEpollFd,EPOLL_CTL_ADD,mWakeReadPipeFd,&
eventItem);
37
LOG_ALWAYS_FATAL_IF(result!=0,
"Could
notaddwakereadpipetoepollinstance.errno=%d"
,
38
errno
);
39
}
40
41
void
Looper::initTLSKey()
{
42
int
result
=pthread_key_create(&gTLSKey,threadDestructor);
43
LOG_ALWAYS_FATAL_IF(result!=0,
"Could
notallocateTLSkey."
);
44
}
45
46
void
Looper::threadDestructor(
void
*st)
{
47
Looper*
const
self
=
static_cast
<Looper*>(st);
48
if
(self
!=NULL){
49
self->decStrong((
void
*)threadDestructor);
50
}
51
}
52
53
void
Looper::setForThread(
const
sp<Looper>&
looper){
54
sp<Looper>old=getForThread();
//
alsohasside-effectofinitializingTLS
55
56
if
(looper
!=NULL){
57
looper->incStrong((
void
*)threadDestructor);
58
}
59
60
pthread_setspecific(gTLSKey,looper.get());
61
62
if
(old
!=NULL){
63
old->decStrong((
void
*)threadDestructor);
64
}
65
}
66
67
sp<Looper>Looper::getForThread(){
68
int
result
=pthread_once(&gTLSOnce,initTLSKey);
69
LOG_ALWAYS_FATAL_IF(result!=0,
"pthread_once
failed"
);
70
71
return
(Looper*)pthread_getspecific(gTLSKey);
72
}
关于pthread库提供的线程局部存储API的用法,可以看到,每个线程局部存储对象,都需要一个key,通过pthread_key_create()函数创建,随后各个线程就可以通过这个key并借助于pthread_setspecific()和pthread_getspecific()函数来保存或者获取相应的线程局部存储的变量了。再来看Looper的构造函数。它创建了一个pipe,两个文件描述符。然后设置管道的两个文件描述属性为非阻塞I/O。接着是创建并设置epoll实例。由此我们了解到,android的消息队列是通过epoll机制来实现其Sleep-Wakeup机制的。


唤醒

然后来看当其他线程向Looper线程的MessageQueue中插入了消息时,Looper线程是如何被叫醒的。回忆我们前面看到的MessageQueue类的enqueueMessage()方法,它在最后插入消息之后,有调用一个nativeWake()方法。没错,正是这个nativeWake()方法执行了叫醒Looper线程的动作。那它又是如何叫醒Looper线程的呢?来看它的实现:

view
source

print?

01
static
void
android_os_MessageQueue_nativeWake(JNIEnv*
env,jclassclazz,jintptr){
02
NativeMessageQueue*nativeMessageQueue=
reinterpret_cast
<NativeMessageQueue*>(ptr);
03
return
nativeMessageQueue->wake();
04
}
05
06
//----------------------------------------------------------------------------
07
08
static
JNINativeMethod
gMessageQueueMethods[]={
09
/*name,signature,funcPtr*/
10
{
"nativeInit"
,
"()I"
,
(
void
*)android_os_MessageQueue_nativeInit},
11
{
"nativeDestroy"
,
"(I)V"
,
(
void
*)android_os_MessageQueue_nativeDestroy},
12
{
"nativePollOnce"
,
"(II)V"
,
(
void
*)android_os_MessageQueue_nativePollOnce},
13
{
"nativeWake"
,
"(I)V"
,
(
void
*)android_os_MessageQueue_nativeWake}
14
};
它只是调用了native层的Looper对象的wake()函数。接着再来看nativeLooper的wake()函数:

view
source

print?

01
void
Looper::wake()
{
02
#ifDEBUG_POLL_AND_WAKE
03
ALOGD(
"%p~wake"
,
this
);
04
#endif
05
06
ssize_tnWrite;
07
do
{
08
nWrite=write(mWakeWritePipeFd,
"W"
,
1);
09
}
while
(nWrite
==-1&&
errno
==EINTR);
10
11
if
(nWrite
!=1){
12
if
(
errno
!=
EAGAIN){
13
ALOGW(
"Couldnotwrite
wakesignal,errno=%d"
,
errno
);
14
}
15
}
16
}
它所做的事情,就是向管道的用于写的那个文件中写入一个“W”字符而已。


休眠

接着是Looper线程休眠的过程。我们知道,Looper线程在Looper.loop()方法中,将会不断地从MessageQueue中取出消息,并处理。不难想象,休眠的时机应该是在取出消息的时候。由Looper.loop()方法的code,我们知道,它是通过MessageQueue.next()方法来从消息队列中取出消息的。我们来看MessageQueue.next()方法的实现:

view
source

print?

01
Messagenext(){
02
int
pendingIdleHandlerCount
=-
1
;
//-1onlyduringfirstiteration
03
int
nextPollTimeoutMillis
=
0
;
04
05
for
(;;)
{
06
if
(nextPollTimeoutMillis
!=
0
){
07
Binder.flushPendingCommands();
08
}
09
nativePollOnce(mPtr,nextPollTimeoutMillis);
10
11
synchronized
(
this
)
{
12
//Trytoretrievethenextmessage.Returniffound.
13
final
long
now
=SystemClock.uptimeMillis();
14
MessageprevMsg=
null
;
15
Messagemsg=mMessages;
16
if
(msg
!=
null
&&msg.target==
null
)
{
17
//Stalledbyabarrier.Findthenextasynchronous
messageinthequeue.
18
do
{
19
prevMsg=msg;
20
msg=msg.next;
21
}
while
(msg
!=
null
&&!msg.isAsynchronous());
22
}
23
if
(msg
!=
null
){
24
if
(now
<msg.when){
25
//Nextmessageisnotready.Setatimeout
towakeupwhenitisready.
26
nextPollTimeoutMillis=(
int
)
Math.min(msg.when-now,Integer.MAX_VALUE);
27
}
else
{
28
//Gotamessage.
29
mBlocked=
false
;
30
if
(prevMsg
!=
null
){
31
prevMsg.next=msg.next;
32
}
else
{
33
mMessages=msg.next;
34
}
35
msg.next=
null
;
36
if
(
false
)
Log.v(
"MessageQueue"
,
"Returningmessage:"
+
msg);
37
msg.markInUse();
38
return
msg;
39
}
40
}
else
{
41
//Nomoremessages.
42
nextPollTimeoutMillis=-
1
;
43
}
44
45
//Processthequitmessagenowthatallpendingmessages
havebeenhandled.
46
if
(mQuiting)
{
47
dispose();
48
return
null
;
49
}
50
51
//Iffirsttimeidle,thengetthenumberofidlers
torun.
52
//Idlehandlesonlyrunifthequeueisemptyorif
thefirstmessage
53
//inthequeue(possiblyabarrier)isduetobehandled
inthefuture.
54
if
(pendingIdleHandlerCount
<
0
55
&&(mMessages==
null
||
now<mMessages.when)){
56
pendingIdleHandlerCount=mIdleHandlers.size();
57
}
58
if
(pendingIdleHandlerCount
<=
0
){
59
//Noidlehandlerstorun.Loopandwaitsome
more.
60
mBlocked=
true
;
61
continue
;
62
}
63
64
if
(mPendingIdleHandlers
==
null
){
65
mPendingIdleHandlers=
new
IdleHandler[Math.max(pendingIdleHandlerCount,
4
)];
66
}
67
mPendingIdleHandlers=mIdleHandlers.toArray(mPendingIdleHandlers);
68
}
69
70
//Runtheidlehandlers.
71
//Weonlyeverreachthiscodeblockduringthefirst
iteration.
72
for
(
int
i
=
0
;i<pendingIdleHandlerCount;i++){
73
final
IdleHandler
idler=mPendingIdleHandlers[i];
74
mPendingIdleHandlers[i]=
null
;
//
releasethereferencetothehandler
75
76
boolean
keep
=
false
;
77
try
{
78
keep=idler.queueIdle();
79
}
catch
(Throwable
t){
80
Log.wtf(
"MessageQueue"
,
"IdleHandler
threwexception"
,t);
81
}
82
83
if
(!keep)
{
84
synchronized
(
this
)
{
85
mIdleHandlers.remove(idler);
86
}
87
}
88
}
89
90
//Resettheidlehandlercountto0sowedonotrunthem
again.
91
pendingIdleHandlerCount=
0
;
92
93
//Whilecallinganidlehandler,anewmessagecouldhave
beendelivered
94
//sogobackandlookagainforapendingmessagewithout
waiting.
95
nextPollTimeoutMillis=
0
;
96
}
97
}
值得注意的是上面那个对于nativePollOnce()的调用。wait机制的实现正在于此。来看这个方法的实现,在native的JNIcode里面:

view
source

print?

01
class
MessageQueue
:
public
RefBase{
02
public
:
03
/*Getsthemessagequeue'slooper.*/
04
inline
sp<Looper>
getLooper()
const
{
05
return
mLooper;
06
}
07
08
/*CheckswhethertheJNIenvironmenthasapendingexception.
09
*
10
*Ifanexceptionoccurred,logsittogetherwiththespecified
message,
11
*andcallsraiseException()toensuretheexceptionwillbe
raisedwhen
12
*thecallbackreturns,clearsthependingexceptionfromthe
environment,
13
*thenreturnstrue.
14
*
15
*Ifnoexceptionoccurred,returnsfalse.
16
*/
17
bool
raiseAndClearException(JNIEnv*
env,
const
char
*
msg);
18
19
/*Raisesanexceptionfromwithinacallbackfunction.
20
*Theexceptionwillberethrownwhencontrolreturnstothe
messagequeuewhich
21
*willtypicallycausetheapplicationtocrash.
22
*
23
*Thismessagecanonlybecalledfromwithinacallbackfunction.
Ifitiscalled
24
*atanyothertime,theprocesswillsimplybekilled.
25
*
26
*DoesnothingifexceptionisNULL.
27
*
28
*(Thismethoddoesnottakeownershipoftheexceptionobject
reference.
29
*Thecallerisresponsibleforreleasingitsreferencewhen
itisdone.)
30
*/
31
virtual
void
raiseException(JNIEnv*
env,
const
char
*
msg,jthrowableexceptionObj)=0;
32
33
protected
:
34
MessageQueue();
35
virtual
~MessageQueue();
36
37
protected
:
38
sp<Looper>mLooper;
39
};
40
41
class
NativeMessageQueue
:
public
MessageQueue{
42
public
:
43
NativeMessageQueue();
44
virtual
~NativeMessageQueue();
45
46
virtual
void
raiseException(JNIEnv*
env,
const
char
*
msg,jthrowableexceptionObj);
47
48
void
pollOnce(JNIEnv*
env,
int
timeoutMillis);
49
50
void
wake();
51
52
private
:
53
bool
mInCallback;
54
jthrowablemExceptionObj;
55
};
56
57
void
NativeMessageQueue::pollOnce(JNIEnv*
env,
int
timeoutMillis){
58
mInCallback=
true
;
59
mLooper->pollOnce(timeoutMillis);
60
mInCallback=
false
;
61
if
(mExceptionObj)
{
62
env->Throw(mExceptionObj);
63
env->DeleteLocalRef(mExceptionObj);
64
mExceptionObj=NULL;
65
}
66
}
67
68
static
void
android_os_MessageQueue_nativePollOnce(JNIEnv*
env,jclassclazz,
69
jintptr,jinttimeoutMillis){
70
NativeMessageQueue*nativeMessageQueue=
reinterpret_cast
<NativeMessageQueue*>(ptr);
71
nativeMessageQueue->pollOnce(env,timeoutMillis);
72
}
继续追Looper::pollOnce()的实现(在frameworks/native/libs/utils/Looper.cpp):

view
source

print?

001
int
Looper::pollOnce(
int
timeoutMillis,
int
*
outFd,
int
*outEvents,
void
**outData){
002
int
result
=0;
003
for
(;;)
{
004
while
(mResponseIndex
<mResponses.size()){
005
const
Response&
response=mResponses.itemAt(mResponseIndex++);
006
int
ident
=response.request.ident;
007
if
(ident
>=0){
008
int
fd
=response.request.fd;
009
int
events
=response.events;
010
void
*data=
response.request.data;
011
#ifDEBUG_POLL_AND_WAKE
012
ALOGD(
"%p~pollOnce
-returningsignalledidentifier%d:"
013
"fd=%d,events=0x%x,data=%p"
,
014
this
,
ident,fd,events,data);
015
#endif
016
if
(outFd
!=NULL)*outFd=fd;
017
if
(outEvents
!=NULL)*outEvents=events;
018
if
(outData
!=NULL)*outData=data;
019
return
ident;
020
}
021
}
022
023
if
(result
!=0){
024
#ifDEBUG_POLL_AND_WAKE
025
ALOGD(
"%p~pollOnce-
returningresult%d"
,
this
,result);
026
#endif
027
if
(outFd
!=NULL)*outFd=0;
028
if
(outEvents
!=NULL)*outEvents=0;
029
if
(outData
!=NULL)*outData=NULL;
030
return
result;
031
}
032
033
result=pollInner(timeoutMillis);
034
}
035
}
036
037
int
Looper::pollInner(
int
timeoutMillis)
{
038
#ifDEBUG_POLL_AND_WAKE
039
ALOGD(
"%p~pollOnce-waiting:
timeoutMillis=%d"
,
this
,timeoutMillis);
040
#endif
041
042
//Adjustthetimeoutbasedonwhenthenextmessageisdue.
043
if
(timeoutMillis
!=0&&mNextMessageUptime!=LLONG_MAX){
044
nsecs_tnow=systemTime(SYSTEM_TIME_MONOTONIC);
045
int
messageTimeoutMillis
=toMillisecondTimeoutDelay(now,mNextMessageUptime);
046
if
(messageTimeoutMillis
>=0
047
&&(timeoutMillis<0||messageTimeoutMillis<timeoutMillis))
{
048
timeoutMillis=messageTimeoutMillis;
049
}
050
#ifDEBUG_POLL_AND_WAKE
051
ALOGD(
"%p~pollOnce-next
messagein%lldns,adjustedtimeout:timeoutMillis=%d"
,
052
this
,mNextMessageUptime
-now,timeoutMillis);
053
#endif
054
}
055
056
//Poll.
057
int
result
=ALOOPER_POLL_WAKE;
058
mResponses.clear();
059
mResponseIndex=0;
060
061
struct
epoll_event
eventItems[EPOLL_MAX_EVENTS];
062
int
eventCount
=epoll_wait(mEpollFd,eventItems,EPOLL_MAX_EVENTS,timeoutMillis);
063
064
//Acquirelock.
065
mLock.lock();
066
067
//Checkforpollerror.
068
if
(eventCount
<0){
069
if
(
errno
==
EINTR){
070
goto
Done;
071
}
072
ALOGW(
"Pollfailedwithan
unexpectederror,errno=%d"
,
errno
);
073
result=ALOOPER_POLL_ERROR;
074
goto
Done;
075
}
076
077
//Checkforpolltimeout.
078
if
(eventCount
==0){
079
#ifDEBUG_POLL_AND_WAKE
080
ALOGD(
"%p~pollOnce-timeout"
,
this
);
081
#endif
082
result=ALOOPER_POLL_TIMEOUT;
083
goto
Done;
084
}
085
086
//Handleallevents.
087
#ifDEBUG_POLL_AND_WAKE
088
ALOGD(
"%p~pollOnce-handling
eventsfrom%dfds"
,
this
,eventCount);
089
#endif
090
091
for
(
int
i
=0;i<eventCount;i++){
092
int
fd
=eventItems[i].data.fd;
093
uint32_tepollEvents=eventItems[i].events;
094
if
(fd
==mWakeReadPipeFd){
095
if
(epollEvents
&EPOLLIN){
096
awoken();
097
}
else
{
098
ALOGW(
"Ignoringunexpected
epollevents0x%xonwakereadpipe."
,epollEvents);
099
}
100
}
else
{
101
ssize_trequestIndex=mRequests.indexOfKey(fd);
102
if
(requestIndex
>=0){
103
int
events
=0;
104
if
(epollEvents
&EPOLLIN)events|=ALOOPER_EVENT_INPUT;
105
if
(epollEvents
&EPOLLOUT)events|=ALOOPER_EVENT_OUTPUT;
106
if
(epollEvents
&EPOLLERR)events|=ALOOPER_EVENT_ERROR;
107
if
(epollEvents
&EPOLLHUP)events|=ALOOPER_EVENT_HANGUP;
108
pushResponse(events,mRequests.valueAt(requestIndex));
109
}
else
{
110
ALOGW(
"Ignoringunexpected
epollevents0x%xonfd%dthatis"
111
"nolongerregistered."
,
epollEvents,fd);
112
}
113
}
114
}
115
Done:;
116
117
//Invokependingmessagecallbacks.
118
mNextMessageUptime=LLONG_MAX;
119
while
(mMessageEnvelopes.size()
!=0){
120
nsecs_tnow=systemTime(SYSTEM_TIME_MONOTONIC);
121
const
MessageEnvelope&
messageEnvelope=mMessageEnvelopes.itemAt(0);
122
if
(messageEnvelope.uptime
<=now){
123
//Removetheenvelopefromthelist.
124
//Wekeepastrongreferencetothehandleruntilthe
calltohandleMessage
125
//finishes.Thenwedropitsothatthehandlercan
bedeleted*before*
126
//wereacquireourlock.
127
{
//obtainhandler
128
sp<MessageHandler>handler=messageEnvelope.handler;
129
Messagemessage=messageEnvelope.message;
130
mMessageEnvelopes.removeAt(0);
131
mSendingMessage=
true
;
132
mLock.unlock();
133
134
#ifDEBUG_POLL_AND_WAKE||DEBUG_CALLBACKS
135
ALOGD(
"%p~pollOnce
-sendingmessage:handler=%p,what=%d"
,
136
this
,
handler.get(),message.what);
137
#endif
138
handler->handleMessage(message);
139
}
//releasehandler
140
141
mLock.lock();
142
mSendingMessage=
false
;
143
result=ALOOPER_POLL_CALLBACK;
144
}
else
{
145
//Thelastmessageleftattheheadofthequeuedetermines
thenextwakeuptime.
146
mNextMessageUptime=messageEnvelope.uptime;
147
break
;
148
}
149
}
150
151
//Releaselock.
152
mLock.unlock();
153
154
//Invokeallresponsecallbacks.
155
for
(
size_t
i
=0;i<mResponses.size();i++){
156
Response&response=mResponses.editItemAt(i);
157
if
(response.request.ident
==ALOOPER_POLL_CALLBACK){
158
int
fd
=response.request.fd;
159
int
events
=response.events;
160
void
*data=response.request.data;
161
#ifDEBUG_POLL_AND_WAKE||DEBUG_CALLBACKS
162
ALOGD(
"%p~pollOnce-
invokingfdeventcallback%p:fd=%d,events=0x%x,data=%p"
,
163
this
,response.request.callback.get(),
fd,events,data);
164
#endif
165
int
callbackResult
=response.request.callback->handleEvent(fd,events,data);
166
if
(callbackResult
==0){
167
removeFd(fd);
168
}
169
//Clearthecallbackreferenceintheresponsestructure
promptlybecausewe
170
//willnotcleartheresponsevectoritselfuntilthe
nextpoll.
171
response.request.callback.clear();
172
result=ALOOPER_POLL_CALLBACK;
173
}
174
}
175
return
result;
176
}
它通过调用epoll_wait()函数来等待消息的到来。

Done。

转载自http://my.oschina.net/wolfcs/blog/160601
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android