android的消息队列机制
来源:互联网 发布:网络间接市场调研方法 编辑:程序博客网 时间:2024/06/06 08:47
Looper线程
我们知道,线程是进程中某个单一顺序的控制流,它是内核做CPU调度的单位。那何为Looper线程呢?所谓Looper线程,即是借助于Looper和MessageQueue来管理控制流的一类线程。在android系统中,application的主线程即是借助于Looper和MessageQueue来管理控制流的。其实,不仅仅只有主线程可以用Looper和MessageQueue来管理控制流,其他的线程也一样可以。我们可以先看一下android source code的注释中给出的一种Looper线程的实现方式:
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
// process incoming message here
22
}
23
};
24
25
Looper.loop();
26
}
27
}
可以看到,就是在线程的run()方法中,调用Looper.prepare()做一些初始化,然后创建一个Handler对象,最后执行Looper.loop()即开始了整个的事件循环。就是这么的简单,一个可以使用消息队列来管理线程执行流程的Looper 线程就创建好了。
接着我们来看一下,神秘的Looper.prepare()到底都干了些什么事情:
01
// sThreadLocal.get() will return null unless you've called prepare().
02
static
final
ThreadLocal<Looper> sThreadLocal =
new
ThreadLocal<Looper>();
03
04
/** Initialize the current thread as a looper.
05
* This gives you a chance to create handlers that then reference
06
* this looper, before actually starting the loop. Be sure to call
07
* {@link #loop()} after calling this method, and end it by 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 one Looper may be created per thread"
);
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线程就和启动普通的线程一样,比如:
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线程,另外一种则是main loop线程,创建前者使用我们前面看到的Looper.prepare()方法,而要创建后者,我们则可以使用Looper.prepareMainLooper()方法。可以看一下Looper.prepareMainLooper()的实现:
01
/**
02
* Initialize the current thread as a looper, marking it as an
03
* application's main looper. The main looper for your application
04
* is created by the Android environment, so you should never need
05
* to call this function yourself. See also: {@link #prepare()}
06
*/
07
public
static
void
prepareMainLooper() {
08
prepare(
false
);
09
synchronized
(Looper.
class
) {
10
if
(sMainLooper !=
null
) {
11
throw
new
IllegalStateException(
"The main Looper has already been prepared."
);
12
}
13
sMainLooper = myLooper();
14
}
15
}
比较特别的地方即在于,此处调用prepare()方法传进去的参数为false,即表示这个Looper不能够被quit掉。其他倒是基本一样。整个android系统中,调用到prepareMainLooper()方法的大概有两处:
1
/frameworks/base/services/java/com/android/server/
2
H A D SystemServer.java
94
Looper.prepareMainLooper();
3
/frameworks/base/core/java/android/app/
4
H A D ActivityThread.java
5087
Looper.prepareMainLooper();
一处在ServerThread的run()方法中,用于为system server主线程初始化消息队列等,另外一处在ActivityThread的run()方法中,自然即是创建android app主线程的消息队列了。
通过消息与Looper线程交互
那Looper线程的特别之处究竟在哪里呢?如前所述,这种线程有一个Looper与之关联,这种线程会使用消息队列,或者称为事件循环来管理执行的流程。那这种特别之处又如何体现呢?其他线程可以向此类线程中丢消息进来,当然此类线程本身也可以往自己的消息队列里面丢消息,然后在事件循环中,这种事件会得到有效的处理。那究竟要如何往Looper线程的消息队列中发送消息呢?
回忆我们前面创建Looper线程的那个code,我们不是有创建出来一个Handler嘛。没错,我们就是通过Handler来向Looper线程的MessageQueue中发送消息的。可以看一下code的写法。先是LooperThread的写法:
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
// process incoming message
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线程发送消息的部分的写法:
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
LooperThread mThread;
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
Handler handler = mThread.mHandler;
39
Message msg = 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
Handler handler = mThread.mHandler;
50
Message msg = 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
Handler handler = mThread.mHandler;
61
Message msg = 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
Handler handler = mThread.mHandler;
72
Message msg = 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
Handler handler = mThread.mHandler;
83
Message msg = Message.obtain();
84
msg.what = MESSAGE_WHAT_DESTROY;
85
handler.sendMessage(msg);
86
}
87
88
@Override
<span style=
"color: rgb(229, 51, 51);"
></span>
public
boolean
onCreateOptionsMenu(Menu menu) {
89
// Inflate the menu; this adds items to the action bar if it is present.
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对象构造的过程:
001
/**
002
* Default constructor associates this handler with the {@link Looper} for the
003
* current thread.
004
*
005
* If this thread does not have a looper, this handler won't be able to receive messages
006
* so an exception is thrown.
007
*/
008
public
Handler() {
009
this
(
null
,
false
);
010
}
011
012
/**
013
* Constructor associates this handler with the {@link Looper} for the
014
* current thread and takes a callback interface in which you can handle
015
* messages.
016
*
017
* If this thread does not have a looper, this handler won't be able to receive messages
018
* so an exception is thrown.
019
*
020
* @param callback The callback interface in which to handle messages, or null.
021
*/
022
public
Handler(Callback callback) {
023
this
(callback,
false
);
024
}
025
026
/**
027
* Use the provided {@link Looper} instead of the default one.
028
*
029
* @param looper The looper, must not be null.
030
*/
031
public
Handler(Looper looper) {
032
this
(looper,
null
,
false
);
033
}
034
035
/**
036
* Use the provided {@link Looper} instead of the default one and take a callback
037
* interface in which to handle messages.
038
*
039
* @param looper The looper, must not be null.
040
* @param callback The callback interface in which to handle messages, or null.
041
*/
042
public
Handler(Looper looper, Callback callback) {
043
this
(looper, callback,
false
);
044
}
045
046
/**
047
* Use the {@link Looper} for the current thread
048
* and set whether the handler should be asynchronous.
049
*
050
* Handlers are synchronous by default unless this constructor is used to make
051
* one that is strictly asynchronous.
052
*
053
* Asynchronous messages represent interrupts or events that do not require global ordering
054
* with represent to synchronous messages. Asynchronous messages are not subject to
055
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier long)}.
056
*
057
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
058
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
059
*
060
* @hide
061
*/
062
public
Handler(
boolean
async) {
063
this
(
null
, async);
064
}
065
066
/**
067
* Use the {@link Looper} for the current thread with the specified callback interface
068
* and set whether the handler should be asynchronous.
069
*
070
* Handlers are synchronous by default unless this constructor is used to make
071
* one that is strictly asynchronous.
072
*
073
* Asynchronous messages represent interrupts or events that do not require global ordering
074
* with represent to synchronous messages. Asynchronous messages are not subject to
075
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier long)}.
076
*
077
* @param callback The callback interface in which to handle messages, or null.
078
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
079
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
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,
"The following Handler class should be static or leaks might occur: "
+
089
klass.getCanonicalName());
090
}
091
}
092
093
mLooper = Looper.myLooper();
094
if
(mLooper ==
null
) {
095
throw
new
RuntimeException(
096
"Can't create handler inside thread that has not called 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()族的实现:
001
/**
002
* Pushes a message onto the end of the message queue after all pending messages
003
* before the current time. It will be received in {@link #handleMessage},
004
* in the thread attached to this handler.
005
*
006
* @return Returns true if the message was successfully placed in to the
007
* message queue. Returns false on failure, usually because the
008
* looper processing the message queue is exiting.
009
*/
010
public
final
boolean
sendMessage(Message msg)
011
{
012
return
sendMessageDelayed(msg,
0
);
013
}
014
015
/**
016
* Sends a Message containing only the what value.
017
*
018
* @return Returns true if the message was successfully placed in to the
019
* message queue. Returns false on failure, usually because the
020
* looper processing the message queue is exiting.
021
*/
022
public
final
boolean
sendEmptyMessage(
int
what)
023
{
024
return
sendEmptyMessageDelayed(what,
0
);
025
}
026
027
/**
028
* Sends a Message containing only the what value, to be delivered
029
* after the specified amount of time elapses.
030
* @see #sendMessageDelayed(android.os.Message, long)
031
*
032
* @return Returns true if the message was successfully placed in to the
033
* message queue. Returns false on failure, usually because the
034
* looper processing the message queue is exiting.
035
*/
036
public
final
boolean
sendEmptyMessageDelayed(
int
what,
long
delayMillis) {
037
Message msg = Message.obtain();
038
msg.what = what;
039
return
sendMessageDelayed(msg, delayMillis);
040
}
041
042
/**
043
* Sends a Message containing only the what value, to be delivered
044
* at a specific time.
045
* @see #sendMessageAtTime(android.os.Message, long)
046
*
047
* @return Returns true if the message was successfully placed in to the
048
* message queue. Returns false on failure, usually because the
049
* looper processing the message queue is exiting.
050
*/
051
052
public
final
boolean
sendEmptyMessageAtTime(
int
what,
long
uptimeMillis) {
053
Message msg = Message.obtain();
054
msg.what = what;
055
return
sendMessageAtTime(msg, uptimeMillis);
056
}
057
058
/**
059
* Enqueue a message into the message queue after all pending messages
060
* before (current time + delayMillis). You will receive it in
061
* {@link #handleMessage}, in the thread attached to this handler.
062
*
063
* @return Returns true if the message was successfully placed in to the
064
* message queue. Returns false on failure, usually because the
065
* looper processing the message queue is exiting. Note that a
066
* result of true does not mean the message will be processed -- if
067
* the looper is quit before the delivery time of the message
068
* occurs then the message will be dropped.
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
* Enqueue a message into the message queue after all pending messages
080
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
081
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
082
* You will receive it in {@link #handleMessage}, in the thread attached
083
* to this handler.
084
*
085
* @param uptimeMillis The absolute time at which the message should be
086
* delivered, using the
087
* {@link android.os.SystemClock#uptimeMillis} time-base.
088
*
089
* @return Returns true if the message was successfully placed in to the
090
* message queue. Returns false on failure, usually because the
091
* looper processing the message queue is exiting. Note that a
092
* result of true does not mean the message will be processed -- if
093
* the looper is quit before the delivery time of the message
094
* occurs then the message will be dropped.
095
*/
096
public
boolean
sendMessageAtTime(Message msg,
long
uptimeMillis) {
097
MessageQueue queue = mQueue;
098
if
(queue ==
null
) {
099
RuntimeException e =
new
RuntimeException(
100
this
+
" sendMessageAtTime() called with no mQueue"
);
101
Log.w(
"Looper"
, e.getMessage(), e);
102
return
false
;
103
}
104
return
enqueueMessage(queue, msg, uptimeMillis);
105
}
106
107
/**
108
* Enqueue a message at the front of the message queue, to be processed on
109
* the next iteration of the message loop. You will receive it in
110
* {@link #handleMessage}, in the thread attached to this handler.
111
* <b>This method is only for use in very special circumstances -- it
112
* can easily starve the message queue, cause ordering problems, or have
113
* other unexpected side-effects.</b>
114
*
115
* @return Returns true if the message was successfully placed in to the
116
* message queue. Returns false on failure, usually because the
117
* looper processing the message queue is exiting.
118
*/
119
public
final
boolean
sendMessageAtFrontOfQueue(Message msg) {
120
MessageQueue queue = mQueue;
121
if
(queue ==
null
) {
122
RuntimeException e =
new
RuntimeException(
123
this
+
" sendMessageAtTime() called with no mQueue"
);
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, Message msg,
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/handle message时将会使用的Handler。即,在default情况下,处理message的那个handler也将会是发送此message的handler。
Handler实际的职责,并不像它的名称所显示的那样,其实它不仅仅是处理message,它还负责发送Message给线程的MessageQueue。
再来看一下MessageQueue的enqueueMessage()方法的code:
01
boolean
enqueueMessage(Message msg,
long
when) {
02
if
(msg.isInUse()) {
03
throw
new
AndroidRuntimeException(msg +
" This message is already in use."
);
04
}
05
if
(msg.target ==
null
) {
06
throw
new
AndroidRuntimeException(
"Message must have a target."
);
07
}
08
09
boolean
needWake;
10
synchronized
(
this
) {
11
if
(mQuiting) {
12
RuntimeException e =
new
RuntimeException(
13
msg.target +
" sending message to a Handler on a dead thread"
);
14
Log.w(
"MessageQueue"
, e.getMessage(), e);
15
return
false
;
16
}
17
18
msg.when = when;
19
Message p = mMessages;
20
if
(p ==
null
|| when ==
0
|| when < p.when) {
21
// New head, wake up the event queue if blocked.
22
msg.next = p;
23
mMessages = msg;
24
needWake = mBlocked;
25
}
else
{
26
// Inserted within the middle of the queue. Usually we don't have to wake
27
// up the event queue unless there is a barrier at the head of the queue
28
// and the message is the earliest asynchronous message in the queue.
29
needWake = mBlocked && p.target ==
null
&& msg.isAsynchronous();
30
Message prev;
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()族方法也大同小异啦:
01
/**
02
* Causes the Runnable r to be added to the message queue.
03
* The runnable will be run on the thread to which this handler is
04
* attached.
05
*
06
* @param r The Runnable that will be executed.
07
*
08
* @return Returns true if the Runnable was successfully placed in to the
09
* message queue. Returns false on failure, usually because the
10
* looper processing the message queue is exiting.
11
*/
12
public
final
boolean
post(Runnable r)
13
{
14
return
sendMessageDelayed(getPostMessage(r),
0
);
15
}
16
17
private
static
Message getPostMessage(Runnable r) {
18
Message m = Message.obtain();
19
m.callback = r;
20
return
m;
21
}
Post的message,其callback将是传入的Runnable对象,其他就与send的message一样了。
消息队列中消息的处理
消息队列中的消息是在Looper.loop()中被处理的:
01
/**
02
* Run the message queue in this thread. Be sure to call
03
* {@link #quit()} to end the loop.
04
*/
05
public
static
void
loop() {
06
final
Looper me = myLooper();
07
if
(me ==
null
) {
08
throw
new
RuntimeException(
"No Looper; Looper.prepare() wasn't called on this thread."
);
09
}
10
final
MessageQueue queue = me.mQueue;
11
12
// Make sure the identity of this thread is that of the local process,
13
// and keep track of what that identity token actually is.
14
Binder.clearCallingIdentity();
15
final
long
ident = Binder.clearCallingIdentity();
16
17
for
(;;) {
18
Message msg = queue.next();
// might block
19
if
(msg ==
null
) {
20
// No message indicates that the message queue is quitting.
21
return
;
22
}
23
24
// This must be in a local variable, in case a UI event sets the logger
25
Printer logging = me.mLogging;
26
if
(logging !=
null
) {
27
logging.println(
">>>>> Dispatching to "
+ msg.target +
" "
+
28
msg.callback +
": "
+ msg.what);
29
}
30
31
msg.target.dispatchMessage(msg);
32
33
if
(logging !=
null
) {
34
logging.println(
"<<<<< Finished to "
+ msg.target +
" "
+ msg.callback);
35
}
36
37
// Make sure that during the course of dispatching the
38
// identity of the thread wasn't corrupted.
39
final
long
newIdent = Binder.clearCallingIdentity();
40
if
(ident != newIdent) {
41
Log.wtf(TAG,
"Thread identity changed from 0x"
42
+ Long.toHexString(ident) +
" to 0x"
43
+ Long.toHexString(newIdent) +
" while dispatching to "
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()的实现:
01
/**
02
* Handle system messages here.
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)的实现:
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的构造函数:
1
MessageQueue(
boolean
quitAllowed) {
2
mQuitAllowed = quitAllowed;
3
mPtr = nativeInit();
4
}
这个方法调用nativeInit()方法来创建出Sleep-Wakeup机制所需设施。我们来看nativeInit()的实现(在frameworks/base/core/jni/android_os_MessageQueue.cpp中):
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, jclass clazz) {
10
NativeMessageQueue* nativeMessageQueue =
new
NativeMessageQueue();
11
if
(!nativeMessageQueue) {
12
jniThrowRuntimeException(env,
"Unable to allocate native queue"
);
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):
01
// Hint for number of file descriptors to be associated with the epoll instance.
02
static
const
int
EPOLL_SIZE_HINT = 8;
03
04
// Maximum number of file descriptors for which to retrieve poll events each iteration.
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 not create wake pipe. 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 not make wake read pipe non-blocking. errno=%d"
,
22
errno
);
23
24
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
25
LOG_ALWAYS_FATAL_IF(result != 0,
"Could not make wake write pipe non-blocking. errno=%d"
,
26
errno
);
27
28
// Allocate the epoll instance and register the wake pipe.
29
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
30
LOG_ALWAYS_FATAL_IF(mEpollFd < 0,
"Could not create epoll instance. errno=%d"
,
errno
);
31
32
struct
epoll_event eventItem;
33
memset
(& eventItem, 0,
sizeof
(epoll_event));
// zero out unused members of data field union
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 not add wake read pipe to epoll instance. 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 not allocate TLS key."
);
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();
// also has side-effect of initializing TLS
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线程的呢?来看它的实现:
01
static
void
android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jint ptr) {
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()函数。接着再来看native Looper的wake()函数:
01
void
Looper::wake() {
02
#if DEBUG_POLL_AND_WAKE
03
ALOGD(
"%p ~ wake"
,
this
);
04
#endif
05
06
ssize_t nWrite;
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(
"Could not write wake signal, errno=%d"
,
errno
);
14
}
15
}
16
}
它所做的事情,就是向管道的用于写的那个文件中写入一个“W”字符而已。
休眠
接着是Looper线程休眠的过程。我们知道,Looper线程在Looper.loop()方法中,将会不断地从MessageQueue中取出消息,并处理。不难想象,休眠的时机应该是在取出消息的时候。由Looper.loop()方法的code,我们知道,它是通过MessageQueue.next()方法来从消息队列中取出消息的。我们来看MessageQueue.next()方法的实现:
01
Message next() {
02
int
pendingIdleHandlerCount = -
1
;
// -1 only during first iteration
03
int
nextPollTimeoutMillis =
0
;
04
05
for
(;;) {
06
if
(nextPollTimeoutMillis !=
0
) {
07
Binder.flushPendingCommands();
08
}
09
nativePollOnce(mPtr, nextPollTimeoutMillis);
10
11
synchronized
(
this
) {
12
// Try to retrieve the next message. Return if found.
13
final
long
now = SystemClock.uptimeMillis();
14
Message prevMsg =
null
;
15
Message msg = mMessages;
16
if
(msg !=
null
&& msg.target ==
null
) {
17
// Stalled by a barrier. Find the next asynchronous message in the queue.
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
// Next message is not ready. Set a timeout to wake up when it is ready.
26
nextPollTimeoutMillis = (
int
) Math.min(msg.when - now, Integer.MAX_VALUE);
27
}
else
{
28
// Got a message.
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"
,
"Returning message: "
+ msg);
37
msg.markInUse();
38
return
msg;
39
}
40
}
else
{
41
// No more messages.
42
nextPollTimeoutMillis = -
1
;
43
}
44
45
// Process the quit message now that all pending messages have been handled.
46
if
(mQuiting) {
47
dispose();
48
return
null
;
49
}
50
51
// If first time idle, then get the number of idlers to run.
52
// Idle handles only run if the queue is empty or if the first message
53
// in the queue (possibly a barrier) is due to be handled in the future.
54
if
(pendingIdleHandlerCount <
0
55
&& (mMessages ==
null
|| now < mMessages.when)) {
56
pendingIdleHandlerCount = mIdleHandlers.size();
57
}
58
if
(pendingIdleHandlerCount <=
0
) {
59
// No idle handlers to run. Loop and wait some 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
// Run the idle handlers.
71
// We only ever reach this code block during the first iteration.
72
for
(
int
i =
0
; i < pendingIdleHandlerCount; i++) {
73
final
IdleHandler idler = mPendingIdleHandlers[i];
74
mPendingIdleHandlers[i] =
null
;
// release the reference to the handler
75
76
boolean
keep =
false
;
77
try
{
78
keep = idler.queueIdle();
79
}
catch
(Throwable t) {
80
Log.wtf(
"MessageQueue"
,
"IdleHandler threw exception"
, t);
81
}
82
83
if
(!keep) {
84
synchronized
(
this
) {
85
mIdleHandlers.remove(idler);
86
}
87
}
88
}
89
90
// Reset the idle handler count to 0 so we do not run them again.
91
pendingIdleHandlerCount =
0
;
92
93
// While calling an idle handler, a new message could have been delivered
94
// so go back and look again for a pending message without waiting.
95
nextPollTimeoutMillis =
0
;
96
}
97
}
值得注意的是上面那个对于nativePollOnce()的调用。wait机制的实现正在于此。来看这个方法的实现,在native的JNI code里面:
01
class
MessageQueue :
public
RefBase {
02
public
:
03
/* Gets the message queue's looper. */
04
inline
sp<Looper> getLooper()
const
{
05
return
mLooper;
06
}
07
08
/* Checks whether the JNI environment has a pending exception.
09
*
10
* If an exception occurred, logs it together with the specified message,
11
* and calls raiseException() to ensure the exception will be raised when
12
* the callback returns, clears the pending exception from the environment,
13
* then returns true.
14
*
15
* If no exception occurred, returns false.
16
*/
17
bool
raiseAndClearException(JNIEnv* env,
const
char
* msg);
18
19
/* Raises an exception from within a callback function.
20
* The exception will be rethrown when control returns to the message queue which
21
* will typically cause the application to crash.
22
*
23
* This message can only be called from within a callback function. If it is called
24
* at any other time, the process will simply be killed.
25
*
26
* Does nothing if exception is NULL.
27
*
28
* (This method does not take ownership of the exception object reference.
29
* The caller is responsible for releasing its reference when it is done.)
30
*/
31
virtual
void
raiseException(JNIEnv* env,
const
char
* msg, jthrowable exceptionObj) = 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, jthrowable exceptionObj);
47
48
void
pollOnce(JNIEnv* env,
int
timeoutMillis);
49
50
void
wake();
51
52
private
:
53
bool
mInCallback;
54
jthrowable mExceptionObj;
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, jclass clazz,
69
jint ptr, jint timeoutMillis) {
70
NativeMessageQueue* nativeMessageQueue =
reinterpret_cast
<NativeMessageQueue*>(ptr);
71
nativeMessageQueue->pollOnce(env, timeoutMillis);
72
}
继续追Looper::pollOnce()的实现(在frameworks/native/libs/utils/Looper.cpp):
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
#if DEBUG_POLL_AND_WAKE
012
ALOGD(
"%p ~ pollOnce - returning signalled identifier %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
#if DEBUG_POLL_AND_WAKE
025
ALOGD(
"%p ~ pollOnce - returning result %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
#if DEBUG_POLL_AND_WAKE
039
ALOGD(
"%p ~ pollOnce - waiting: timeoutMillis=%d"
,
this
, timeoutMillis);
040
#endif
041
042
// Adjust the timeout based on when the next message is due.
043
if
(timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
044
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
045
int
messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
046
if
(messageTimeoutMillis >= 0
047
&& (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
048
timeoutMillis = messageTimeoutMillis;
049
}
050
#if DEBUG_POLL_AND_WAKE
051
ALOGD(
"%p ~ pollOnce - next message in %lldns, adjusted timeout: 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
// Acquire lock.
065
mLock.lock();
066
067
// Check for poll error.
068
if
(eventCount < 0) {
069
if
(
errno
== EINTR) {
070
goto
Done;
071
}
072
ALOGW(
"Poll failed with an unexpected error, errno=%d"
,
errno
);
073
result = ALOOPER_POLL_ERROR;
074
goto
Done;
075
}
076
077
// Check for poll timeout.
078
if
(eventCount == 0) {
079
#if DEBUG_POLL_AND_WAKE
080
ALOGD(
"%p ~ pollOnce - timeout"
,
this
);
081
#endif
082
result = ALOOPER_POLL_TIMEOUT;
083
goto
Done;
084
}
085
086
// Handle all events.
087
#if DEBUG_POLL_AND_WAKE
088
ALOGD(
"%p ~ pollOnce - handling events from %d fds"
,
this
, eventCount);
089
#endif
090
091
for
(
int
i = 0; i < eventCount; i++) {
092
int
fd = eventItems[i].data.fd;
093
uint32_t epollEvents = eventItems[i].events;
094
if
(fd == mWakeReadPipeFd) {
095
if
(epollEvents & EPOLLIN) {
096
awoken();
097
}
else
{
098
ALOGW(
"Ignoring unexpected epoll events 0x%x on wake read pipe."
, epollEvents);
099
}
100
}
else
{
101
ssize_t requestIndex = 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(
"Ignoring unexpected epoll events 0x%x on fd %d that is "
111
"no longer registered."
, epollEvents, fd);
112
}
113
}
114
}
115
Done: ;
116
117
// Invoke pending message callbacks.
118
mNextMessageUptime = LLONG_MAX;
119
while
(mMessageEnvelopes.size() != 0) {
120
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
121
const
MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
122
if
(messageEnvelope.uptime <= now) {
123
// Remove the envelope from the list.
124
// We keep a strong reference to the handler until the call to handleMessage
125
// finishes. Then we drop it so that the handler can be deleted *before*
126
// we reacquire our lock.
127
{
// obtain handler
128
sp<MessageHandler> handler = messageEnvelope.handler;
129
Message message = messageEnvelope.message;
130
mMessageEnvelopes.removeAt(0);
131
mSendingMessage =
true
;
132
mLock.unlock();
133
134
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
135
ALOGD(
"%p ~ pollOnce - sending message: handler=%p, what=%d"
,
136
this
, handler.get(), message.what);
137
#endif
138
handler->handleMessage(message);
139
}
// release handler
140
141
mLock.lock();
142
mSendingMessage =
false
;
143
result = ALOOPER_POLL_CALLBACK;
144
}
else
{
145
// The last message left at the head of the queue determines the next wakeup time.
146
mNextMessageUptime = messageEnvelope.uptime;
147
break
;
148
}
149
}
150
151
// Release lock.
152
mLock.unlock();
153
154
// Invoke all response callbacks.
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
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
162
ALOGD(
"%p ~ pollOnce - invoking fd event callback %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
// Clear the callback reference in the response structure promptly because we
170
// will not clear the response vector itself until the next poll.
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的消息队列机制
- android的消息队列机制
- android的消息队列机制
- android消息队列机制
- Android消息机制-深入理解消息队列的工作模式
- Android handler消息队列机制
- Android消息机制 异步消息 & 消息队列排序
- Android消息队列及线程机制详解
- Android消息队列及线程机制详解
- Android Looper消息队列处理机制
- Android消息队列及线程机制
- android消息队列机制(Handler)
- Android消息处理机制(二):循环和消息队列的创建
- Android的消息机制
- Android的消息机制
- Android的消息机制
- Android的消息机制
- Android的消息机制
- android 任务栈及启动模式
- apache目录结构以及虚拟目录、虚拟主机配置
- hdu5400--Arithmetic Sequence
- Android 中Canvas的使用
- Linux SSH免密码登陆
- android的消息队列机制
- RT-Thread finsh源码分析: finsh_token.h
- Qt_VS问题
- iOS8 UISearchViewController搜索功能讲解
- Java笔试面试题010
- Android BroadCast 广播的两种注册方式和粘性广播实现
- hdu5372 离散化+树状数组
- HDU 3642 Get The Treasury (线段树扫描线进阶--求长方体重叠3次或以上的体积)
- [搜索]hdu5336