android的消息队列机制
2015-08-18 23:23
447 查看
android下的线程,Looper线程,MessageQueue,Handler,Message等之间的关系,以及Message的send/post及Messagedispatch的过程。
我们知道,线程是进程中某个单一顺序的控制流,它是内核做CPU调度的单位。那何为Looper线程呢?所谓Looper线程,即是借助于Looper和MessageQueue来管理控制流的一类线程。在android系统中,application的主线程即是借助于Looper和MessageQueue来管理控制流的。其实,不仅仅只有主线程可以用Looper和MessageQueue来管理控制流,其他的线程也一样可以。我们可以先看一下android
sourcecode的注释中给出的一种Looper线程的实现方式:
view
source
print?
可以看到,就是在线程的run()方法中,调用Looper.prepare()做一些初始化,然后创建一个Handler对象,最后执行Looper.loop()即开始了整个的事件循环。就是这么的简单,一个可以使用消息队列来管理线程执行流程的Looper线程就创建好了。
接着我们来看一下,神秘的Looper.prepare()到底都干了些什么事情:
view
source
print?
可以看到,它做的事情就是为当前的线程创建了一个Looper对象,并存储在一个静态的线程局部变量中。在Looper的构造函数中创建了MessageQueue,同时Looper会引用到当前的线程,并将一个表示状态的变量mRun设置为true。对于此处的线程局部变量sThreadLocal,可以理解为就是一个HashMap,该HashMap中存放的数据其类型为Looper,而HashMap的key则Thread.currentThread()。
启动Looper线程就和启动普通的线程一样,比如:
view
source
print?
同样是new一个Thread对象,然后执行该对象的start()方法。
其实Looper线程有两种,一种就是我们上面看到的那种普通的Looper线程,另外一种则是mainloop线程,创建前者使用我们前面看到的Looper.prepare()方法,而要创建后者,我们则可以使用Looper.prepareMainLooper()方法。可以看一下Looper.prepareMainLooper()的实现:
view
source
print?
比较特别的地方即在于,此处调用prepare()方法传进去的参数为false,即表示这个Looper不能够被quit掉。其他倒是基本一样。整个android系统中,调用到prepareMainLooper()方法的大概有两处:
view
source
print?
一处在ServerThread的run()方法中,用于为systemserver主线程初始化消息队列等,另外一处在ActivityThread的run()方法中,自然即是创建androidapp主线程的消息队列了。
那Looper线程的特别之处究竟在哪里呢?如前所述,这种线程有一个Looper与之关联,这种线程会使用消息队列,或者称为事件循环来管理执行的流程。那这种特别之处又如何体现呢?其他线程可以向此类线程中丢消息进来,当然此类线程本身也可以往自己的消息队列里面丢消息,然后在事件循环中,这种事件会得到有效的处理。那究竟要如何往Looper线程的消息队列中发送消息呢?
回忆我们前面创建Looper线程的那个code,我们不是有创建出来一个Handler嘛。没错,我们就是通过Handler来向Looper线程的MessageQueue中发送消息的。可以看一下code的写法。先是LooperThread的写法:
view
source
print?
然后是向Looper线程发送消息的部分的写法:
view
source
print?
向一个Looper线程发送消息的过程,基本上即是,调用Message.obtain()或Handler.obtainMessage()获取一个Message对象->设置Message->调用Looper线程中创建的Handler对象来发送消息。
Handler究竟是如何知道要向哪个MessageQueue中发送消息呢,从前面的code中,我们找不到任何将Handler与特定的MessageQueue关联起来的代码,这究竟是怎么回事呢?这也是我们强调要使用Looper线程中创建的Handler对象来向该Looper线程中发送消息的原因。我们可以看一下Handler对象构造的过程:
view
source
print?
可以看到,很简单,是通过Looper.myLooper()获取到当前线程的Looper对象,并与相关的MessageQueue等关联起来的。这也是前面我们在实现Looper线程时,要在其run方法中创建一个public的Handler的依据。当然,我们也可以在构造Handler对象时,显式地使其与特定的Looper对象关联起来。
Handler提供了两组函数用于向一个Looper线程的MessageQueue中发送消息,分别是postXXX()族和sendXXX()族。可以先看一下sendXXX()族的实现:
view
source
print?
绕来绕去,最终都是调用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?
整个将Message放入MessageQueue的算法也还算比较清晰简洁,并没有什么太绕的地方。此处我们可以一览MessageQueue中保存Messages的结构,即,MessageQueue用一个单向链表来保存所有的Message,而链表中各个Message则按照其请求的执行时间先后来排列。
向Looper线程的MessageQueue中发送消息的另外一族方法postXXX(),其实现同前面的sendXXX()族方法也大同小异啦:
view
source
print?
Post的message,其callback将是传入的Runnable对象,其他就与send的message一样了。
消息队列中的消息是在Looper.loop()中被处理的:
view
source
print?
这个函数会调用Handler的dispatchMessage()方法来处理消息,其实也就是msg.target对象的dispatchMessage()方法。此外我们可以看到,在Looper.loop()方法的末尾recycle了从MessageQueue中取出的已经dispatch的消息。从而,我们需要通过Handler向一个Looper线程的MessageQueue中发送消息时,我们只要obtain一个Message然后发送就好了,而不需要自己手动去recycle,这些事情将会由Looper来帮助我们完成。接着来看Handler.dispatchMessage()的实现:
view
source
print?
在Message的callback成员为非空时,会执行handleCallback(msg),否则的话会依据Handler的mCallback是否为空来确定是否要执行mCallback.handleMessage(msg),并执行Handler的handleMessage(msg)。Handler的handleMessage()方法通常需要override,来实现消息处理的主要逻辑。而mCallback则使得开发者可以比较容易的添加一种对Message做一些额外检测的机制,以提升消息处理的效率。
接着我们看一下,Handler.handleCallback(msg)的实现:
view
source
print?
很简单的一个方法。可见post的消息的特殊之处,即,此类消息将完全绕过Handler中用于处理消息的handleMessage()方法,而只会执行消息的sender所实现的Runnable。
还有一个问题,当MessageQueue中没有Messages时,那Looper线程会做什么呢?它会去不停的轮询消息队列中是否有消息吗?计算机科学发展到现在,闭上眼睛我们都能知道,Looper线程将一定不会去轮询的。也确实,android消息队列机制的实现,同样是会在消息队列为空时,让Looper线程去休眠,当消息队列中有了消息之后,再被唤醒。但这样的机制又是如何实现的呢?
我们从Sleep-Wakeup机制所需设施的建立开始看起。回忆前面我们看到的Looper的构造函数,它会创建出来一个MessageQueue对象,而Sleep-Wakeup机制所需设施正是在MessageQueue对象的创建过程中创建出来的。我们接着再来看MessageQueue的构造函数:
view
source
print?
这个方法调用nativeInit()方法来创建出Sleep-Wakeup机制所需设施。我们来看nativeInit()的实现(在frameworks/base/core/jni/android_os_MessageQueue.cpp中):
view
source
print?
可以看到,nativeInit()所做的事情,就是创建一个NativeMessageQueue对象,在NativeMessageQueue的构造函数中,会来创建一个Looper对象。与Java层的Looper对象类似,native层的这种Looper对象也是保存在线程局部存储变量中的,每个线程一个。接着我们来看Looper类的构造函数和Looper::getForThread()函数,来了解一下,native层的线程局部存储API的用法(Looper类的实现在frameworks/native/libs/utils/Looper.cpp):
view
source
print?
关于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?
它只是调用了native层的Looper对象的wake()函数。接着再来看nativeLooper的wake()函数:
view
source
print?
它所做的事情,就是向管道的用于写的那个文件中写入一个“W”字符而已。
接着是Looper线程休眠的过程。我们知道,Looper线程在Looper.loop()方法中,将会不断地从MessageQueue中取出消息,并处理。不难想象,休眠的时机应该是在取出消息的时候。由Looper.loop()方法的code,我们知道,它是通过MessageQueue.next()方法来从消息队列中取出消息的。我们来看MessageQueue.next()方法的实现:
view
source
print?
值得注意的是上面那个对于nativePollOnce()的调用。wait机制的实现正在于此。来看这个方法的实现,在native的JNIcode里面:
view
source
print?
继续追Looper::pollOnce()的实现(在frameworks/native/libs/utils/Looper.cpp):
view
source
print?
它通过调用epoll_wait()函数来等待消息的到来。
Done。
转载自http://my.oschina.net/wolfcs/blog/160601
Looper线程
我们知道,线程是进程中某个单一顺序的控制流,它是内核做CPU调度的单位。那何为Looper线程呢?所谓Looper线程,即是借助于Looper和MessageQueue来管理控制流的一类线程。在android系统中,application的主线程即是借助于Looper和MessageQueue来管理控制流的。其实,不仅仅只有主线程可以用Looper和MessageQueue来管理控制流,其他的线程也一样可以。我们可以先看一下androidsourcecode的注释中给出的一种Looper线程的实现方式:
view
source
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 | } |
接着我们来看一下,神秘的Looper.prepare()到底都干了些什么事情:
view
source
01 | //sThreadLocal.get()willreturnnullunlessyou'vecalledprepare(). |
02 | static final ThreadLocal<Looper> new ThreadLocal<Looper>(); |
03 |
04 | /**Initializethecurrentthreadasalooper. |
05 | *Thisgivesyouachancetocreatehandlersthatthenreference |
06 | *thislooper,beforeactuallystartingtheloop.Besure |
07 | *{@link#loop()}aftercallingthismethod,andenditby |
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 ); |
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线程就和启动普通的线程一样,比如:
view
source
01 | public class MainActivity extends Activity { |
02 | public static final String "MessageQueueDemo" ; |
03 | private static final String CompTAG= "MainActivity" ; |
04 | private LooperThread mLooperThread; |
05 |
06 | @Override |
07 | protected void onCreate(Bundle |
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 | } |
其实Looper线程有两种,一种就是我们上面看到的那种普通的Looper线程,另外一种则是mainloop线程,创建前者使用我们前面看到的Looper.prepare()方法,而要创建后者,我们则可以使用Looper.prepareMainLooper()方法。可以看一下Looper.prepareMainLooper()的实现:
view
source
01 | /** |
02 | *Initializethecurrentthreadasalooper,markingitas |
03 | *application'smainlooper.Themainlooperforyourapplication |
04 | *iscreatedbytheAndroidenvironment,soyoushouldnever |
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 ); |
12 | } |
13 | sMainLooper=myLooper(); |
14 | } |
15 | } |
view
source
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(); |
通过消息与Looper线程交互
那Looper线程的特别之处究竟在哪里呢?如前所述,这种线程有一个Looper与之关联,这种线程会使用消息队列,或者称为事件循环来管理执行的流程。那这种特别之处又如何体现呢?其他线程可以向此类线程中丢消息进来,当然此类线程本身也可以往自己的消息队列里面丢消息,然后在事件循环中,这种事件会得到有效的处理。那究竟要如何往Looper线程的消息队列中发送消息呢?回忆我们前面创建Looper线程的那个code,我们不是有创建出来一个Handler嘛。没错,我们就是通过Handler来向Looper线程的MessageQueue中发送消息的。可以看一下code的写法。先是LooperThread的写法:
view
source
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 |
21 | //processincomingmessage |
22 | Log.d(TAG,CompTAG+ ": " + "Handler-->handleMessage,msg.what=" + msg.what); |
23 | } |
24 | }; |
25 |
26 | Looper.loop(); |
27 | } |
28 |
29 | public Handler |
30 | return mHandler; |
31 | } |
32 | } |
view
source
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 "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 |
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: ></span> public boolean onCreateOptionsMenu(Menu |
89 | //Inflatethemenu;thisaddsitemstotheactionbar |
90 | getMenuInflater().inflate(R.menu.main,menu); |
91 | return true ; |
92 | } |
93 |
94 | @Override |
95 | protected void onSaveInstanceState(Bundle |
96 | Log.d(TAG,CompTAG+ ":" + "Activity-->onSaveInstanceState" ); |
97 | super .onSaveInstanceState(outState); |
98 | } |
99 | } |
Handler究竟是如何知道要向哪个MessageQueue中发送消息呢,从前面的code中,我们找不到任何将Handler与特定的MessageQueue关联起来的代码,这究竟是怎么回事呢?这也是我们强调要使用Looper线程中创建的Handler对象来向该Looper线程中发送消息的原因。我们可以看一下Handler对象构造的过程:
view
source
001 | /** |
002 | *Defaultconstructorassociatesthishandlerwiththe{@link |
003 | *currentthread. |
004 | * |
005 | *Ifthisthreaddoesnothavealooper,thishandlerwon't |
006 | *soanexceptionisthrown. |
007 | */ |
008 | public Handler() { |
009 | this ( null , false ); |
010 | } |
011 |
012 | /** |
013 | *Constructorassociatesthishandlerwiththe{@linkLooper} |
014 | *currentthreadandtakesacallbackinterfaceinwhichyou |
015 | *messages. |
016 | * |
017 | *Ifthisthreaddoesnothavealooper,thishandlerwon't |
018 | *soanexceptionisthrown. |
019 | * |
020 | *@paramcallbackThecallbackinterfaceinwhichtohandle |
021 | */ |
022 | public Handler(Callback |
023 | this (callback, false ); |
024 | } |
025 |
026 | /** |
027 | *Usetheprovided{@linkLooper}insteadofthedefaultone. |
028 | * |
029 | *@paramlooperThelooper,mustnotbenull. |
030 | */ |
031 | public Handler(Looper |
032 | this (looper, null , false ); |
033 | } |
034 |
035 | /** |
036 | *Usetheprovided{@linkLooper}insteadofthedefaultone |
037 | *interfaceinwhichtohandlemessages. |
038 | * |
039 | *@paramlooperThelooper,mustnotbenull. |
040 | *@paramcallbackThecallbackinterfaceinwhichtohandle |
041 | */ |
042 | public Handler(Looper |
043 | this (looper,callback, false ); |
044 | } |
045 |
046 | /** |
047 | *Usethe{@linkLooper}forthecurrentthread |
048 | *andsetwhetherthehandlershouldbeasynchronous. |
049 | * |
050 | *Handlersaresynchronousbydefaultunlessthisconstructor |
051 | *onethatisstrictlyasynchronous. |
052 | * |
053 | *Asynchronousmessagesrepresentinterruptsoreventsthat |
054 | *withrepresenttosynchronousmessages.Asynchronousmessages |
055 | *thesynchronizationbarriersintroducedby{@linkMessageQueue#enqueueSyncBarrier |
056 | * |
057 | *@paramasyncIftrue,thehandlercalls{@linkMessage#setAsynchronous(boolean)} |
058 | *each{@linkMessage}thatissenttoitor{@linkRunnable} |
059 | * |
060 | *@hide |
061 | */ |
062 | public Handler( boolean async) { |
063 | this ( null , async); |
064 | } |
065 |
066 | /** |
067 | *Usethe{@linkLooper}forthecurrentthreadwiththespecified |
068 | *andsetwhetherthehandlershouldbeasynchronous. |
069 | * |
070 | *Handlersaresynchronousbydefaultunlessthisconstructor |
071 | *onethatisstrictlyasynchronous. |
072 | * |
073 | *Asynchronousmessagesrepresentinterruptsoreventsthat |
074 | *withrepresenttosynchronousmessages.Asynchronousmessages |
075 | *thesynchronizationbarriersintroducedby{@linkMessageQueue#enqueueSyncBarrier |
076 | * |
077 | *@paramcallbackThecallbackinterfaceinwhichtohandle |
078 | *@paramasyncIftrue,thehandlercalls{@linkMessage#setAsynchronous(boolean)} |
079 | *each{@linkMessage}thatissenttoitor{@linkRunnable} |
080 | * |
081 | *@hide |
082 | */ |
083 | public Handler(Callback boolean async){ |
084 | if (FIND_POTENTIAL_LEAKS) { |
085 | final Class<? extends Handler> |
086 | if ((klass.isAnonymousClass() |
087 | (klass.getModifiers()&Modifier.STATIC)== 0 ) { |
088 | Log.w(TAG, "Thefollowing + |
089 | klass.getCanonicalName()); |
090 | } |
091 | } |
092 |
093 | mLooper=Looper.myLooper(); |
094 | if (mLooper null ){ |
095 | throw new RuntimeException( |
096 | "Can'tcreatehandlerinsidethreadthathasnotcalled ); |
097 | } |
098 | mQueue=mLooper.mQueue; |
099 | mCallback=callback; |
100 | mAsynchronous=async; |
101 | } |
Handler提供了两组函数用于向一个Looper线程的MessageQueue中发送消息,分别是postXXX()族和sendXXX()族。可以先看一下sendXXX()族的实现:
view
source
001 | /** |
002 | *Pushesamessageontotheendofthemessagequeueafter |
003 | *beforethecurrenttime.Itwillbereceivedin{@link#handleMessage}, |
004 | *inthethreadattachedtothishandler. |
005 | * |
006 | *@returnReturnstrueifthemessagewassuccessfullyplaced |
007 | *messagequeue.Returnsfalseonfailure,usually |
008 | *looperprocessingthemessagequeueisexiting. |
009 | */ |
010 | public final boolean sendMessage(Message msg) |
011 | { |
012 | return sendMessageDelayed(msg, 0 ); |
013 | } |
014 |
015 | /** |
016 | *SendsaMessagecontainingonlythewhatvalue. |
017 | * |
018 | *@returnReturnstrueifthemessagewassuccessfullyplaced |
019 | *messagequeue.Returnsfalseonfailure,usually |
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 |
033 | *messagequeue.Returnsfalseonfailure,usually |
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 |
048 | *messagequeue.Returnsfalseonfailure,usually |
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 |
060 | *before(currenttime+delayMillis).Youwillreceiveit |
061 | *{@link#handleMessage},inthethreadattachedtothishandler. |
062 | * |
063 | *@returnReturnstrueifthemessagewassuccessfullyplaced |
064 | *messagequeue.Returnsfalseonfailure,usually |
065 | *looperprocessingthemessagequeueisexiting. |
066 | *resultoftruedoesnotmeanthemessagewillbe |
067 | *thelooperisquitbeforethedeliverytimeofthe |
068 | *occursthenthemessagewillbedropped. |
069 | */ |
070 | public final boolean sendMessageDelayed(Message long delayMillis) |
071 | { |
072 | if (delayMillis 0 ){ |
073 | delayMillis= 0 ; |
074 | } |
075 | return sendMessageAtTime(msg, |
076 | } |
077 |
078 | /** |
079 | *Enqueueamessageintothemessagequeueafterallpending |
080 | *beforetheabsolutetime(inmilliseconds)<var>uptimeMillis</var>. |
081 | *<b>Thetime-baseis{@linkandroid.os.SystemClock#uptimeMillis}.</b> |
082 | *Youwillreceiveitin{@link#handleMessage},inthethread |
083 | *tothishandler. |
084 | * |
085 | *@paramuptimeMillisTheabsolutetimeatwhichthemessage |
086 | *delivered,usingthe |
087 | *{@linkandroid.os.SystemClock#uptimeMillis}time-base. |
088 | * |
089 | *@returnReturnstrueifthemessagewassuccessfullyplaced |
090 | *messagequeue.Returnsfalseonfailure,usually |
091 | *looperprocessingthemessagequeueisexiting. |
092 | *resultoftruedoesnotmeanthemessagewillbe |
093 | *thelooperisquitbeforethedeliverytimeofthe |
094 | *occursthenthemessagewillbedropped. |
095 | */ |
096 | public boolean sendMessageAtTime(Message long uptimeMillis){ |
097 | MessageQueuequeue=mQueue; |
098 | if (queue null ){ |
099 | RuntimeExceptione= new RuntimeException( |
100 | this + " ); |
101 | Log.w( "Looper" , |
102 | return false ; |
103 | } |
104 | return enqueueMessage(queue, |
105 | } |
106 |
107 | /** |
108 | *Enqueueamessageatthefrontofthemessagequeue,to |
109 | *thenextiterationofthemessageloop.Youwillreceive |
110 | *{@link#handleMessage},inthethreadattachedtothishandler. |
111 | *<b>Thismethodisonlyforuseinveryspecialcircumstances |
112 | *caneasilystarvethemessagequeue,causeorderingproblems, |
113 | *otherunexpectedside-effects.</b> |
114 | * |
115 | *@returnReturnstrueifthemessagewassuccessfullyplaced |
116 | *messagequeue.Returnsfalseonfailure,usually |
117 | *looperprocessingthemessagequeueisexiting. |
118 | */ |
119 | public final boolean sendMessageAtFrontOfQueue(Message |
120 | MessageQueuequeue=mQueue; |
121 | if (queue null ){ |
122 | RuntimeExceptione= new RuntimeException( |
123 | this + " ); |
124 | Log.w( "Looper" , |
125 | return false ; |
126 | } |
127 | return enqueueMessage(queue, 0 ); |
128 | } |
129 |
130 | private boolean enqueueMessage(MessageQueue long uptimeMillis){ |
131 | msg.target= this ; |
132 | if (mAsynchronous) { |
133 | msg.setAsynchronous( true ); |
134 | } |
135 | return queue.enqueueMessage(msg, uptimeMillis); |
136 | } |
Handler实际的职责,并不像它的名称所显示的那样,其实它不仅仅是处理message,它还负责发送Message给线程的MessageQueue。
再来看一下MessageQueue的enqueueMessage()方法的code:
view
source
01 | boolean enqueueMessage(Message long when){ |
02 | if (msg.isInUse()) { |
03 | throw new AndroidRuntimeException(msg "Thismessageisalreadyinuse." ); |
04 | } |
05 | if (msg.target null ){ |
06 | throw new AndroidRuntimeException( "Message ); |
07 | } |
08 |
09 | boolean needWake; |
10 | synchronized ( this ) { |
11 | if (mQuiting) { |
12 | RuntimeExceptione= new RuntimeException( |
13 | msg.target+ " ); |
14 | Log.w( "MessageQueue" , |
15 | return false ; |
16 | } |
17 |
18 | msg.when=when; |
19 | Messagep=mMessages; |
20 | if (p null ||when== 0 || |
21 | //Newhead,wakeuptheeventqueueifblocked. |
22 | msg.next=p; |
23 | mMessages=msg; |
24 | needWake=mBlocked; |
25 | } else { |
26 | //Insertedwithinthemiddleofthequeue.Usually |
27 | //uptheeventqueueunlessthereisabarrierat |
28 | //andthemessageistheearliestasynchronousmessage |
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 |
38 | needWake= false ; |
39 | } |
40 | } |
41 | msg.next=p; //invariant: |
42 | prev.next=msg; |
43 | } |
44 | } |
45 | if (needWake) { |
46 | nativeWake(mPtr); |
47 | } |
48 | return true ; |
49 | } |
向Looper线程的MessageQueue中发送消息的另外一族方法postXXX(),其实现同前面的sendXXX()族方法也大同小异啦:
view
source
01 | /** |
02 | *CausestheRunnablertobeaddedtothemessagequeue. |
03 | *Therunnablewillberunonthethreadtowhichthishandler |
04 | *attached. |
05 | * |
06 | *@paramrTheRunnablethatwillbeexecuted. |
07 | * |
08 | *@returnReturnstrueiftheRunnablewassuccessfullyplaced |
09 | *messagequeue.Returnsfalseonfailure,usually |
10 | *looperprocessingthemessagequeueisexiting. |
11 | */ |
12 | public final boolean post(Runnable r) |
13 | { |
14 | return sendMessageDelayed(getPostMessage(r), 0 ); |
15 | } |
16 |
17 | private static Message |
18 | Messagem=Message.obtain(); |
19 | m.callback=r; |
20 | return m; |
21 | } |
消息队列中消息的处理
消息队列中的消息是在Looper.loop()中被处理的:view
source
01 | /** |
02 | *Runthemessagequeueinthisthread.Besuretocall |
03 | *{@link#quit()}toendtheloop. |
04 | */ |
05 | public static void loop() { |
06 | final Looper |
07 | if (me null ){ |
08 | throw new RuntimeException( "No ); |
09 | } |
10 | final MessageQueue |
11 |
12 | //Makesuretheidentityofthisthreadisthatofthelocal |
13 | //andkeeptrackofwhatthatidentitytokenactuallyis. |
14 | Binder.clearCallingIdentity(); |
15 | final long ident |
16 |
17 | for (;;) { |
18 | Messagemsg=queue.next(); // |
19 | if (msg null ){ |
20 | //Nomessageindicatesthatthemessagequeueisquitting. |
21 | return ; |
22 | } |
23 |
24 | //Thismustbeinalocalvariable,incaseaUIevent |
25 | Printerlogging=me.mLogging; |
26 | if (logging null ){ |
27 | logging.println( ">>>>> +msg.target+ "" + |
28 | msg.callback+ ": " +msg.what); |
29 | } |
30 |
31 | msg.target.dispatchMessage(msg); |
32 |
33 | if (logging null ){ |
34 | logging.println( "<<<<< +msg.target+ "" + msg.callback); |
35 | } |
36 |
37 | //Makesurethatduringthecourseofdispatchingthe |
38 | //identityofthethreadwasn'tcorrupted. |
39 | final long newIdent |
40 | if (ident |
41 | Log.wtf(TAG, "Thread |
42 | +Long.toHexString(ident)+ " |
43 | +Long.toHexString(newIdent)+ " |
44 | +msg.target.getClass().getName()+ " " |
45 | +msg.callback+ " what=" +msg.what); |
46 | } |
47 |
48 | msg.recycle(); |
49 | } |
50 | } |
view
source
01 | /** |
02 | *Handlesystemmessageshere. |
03 | */ |
04 | public void dispatchMessage(Message |
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 | } |
接着我们看一下,Handler.handleCallback(msg)的实现:
view
source
1 | private static void handleCallback(Message |
2 | message.callback.run(); |
3 | } |
Sleep-Wakeup机制
还有一个问题,当MessageQueue中没有Messages时,那Looper线程会做什么呢?它会去不停的轮询消息队列中是否有消息吗?计算机科学发展到现在,闭上眼睛我们都能知道,Looper线程将一定不会去轮询的。也确实,android消息队列机制的实现,同样是会在消息队列为空时,让Looper线程去休眠,当消息队列中有了消息之后,再被唤醒。但这样的机制又是如何实现的呢?
Sleep-Wakeup机制所需设施的建立
我们从Sleep-Wakeup机制所需设施的建立开始看起。回忆前面我们看到的Looper的构造函数,它会创建出来一个MessageQueue对象,而Sleep-Wakeup机制所需设施正是在MessageQueue对象的创建过程中创建出来的。我们接着再来看MessageQueue的构造函数:view
source
1 | MessageQueue( boolean quitAllowed) { |
2 | mQuitAllowed=quitAllowed; |
3 | mPtr=nativeInit(); |
4 | } |
view
source
01 | NativeMessageQueue::NativeMessageQueue():mInCallback( false ), |
02 | mLooper=Looper::getForThread(); |
03 | if (mLooper |
04 | mLooper= new Looper( false ); |
05 | Looper::setForThread(mLooper); |
06 | } |
07 | } |
08 |
09 | static jint |
10 | NativeMessageQueue*nativeMessageQueue= new NativeMessageQueue(); |
11 | if (!nativeMessageQueue) { |
12 | jniThrowRuntimeException(env, "Unable ); |
13 | return 0; |
14 | } |
15 |
16 | nativeMessageQueue->incStrong(env); |
17 | return reinterpret_cast <jint>(nativeMessageQueue); |
18 | } |
19 |
20 | static JNINativeMethod |
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 | }; |
view
source
01 | //Hintfornumberoffiledescriptorstobeassociatedwiththeepollinstance. |
02 | static const int EPOLL_SIZE_HINT |
03 |
04 | //Maximumnumberoffiledescriptorsforwhichtoretrievepolleventseachiteration. |
05 | static const int EPOLL_MAX_EVENTS |
06 |
07 | static pthread_once_t |
08 | static pthread_key_t |
09 |
10 | Looper::Looper( bool allowNonCallbacks) : |
11 | mAllowNonCallbacks(allowNonCallbacks),mSendingMessage( false ), |
12 | mResponseIndex(0),mNextMessageUptime(LLONG_MAX){ |
13 | int wakeFds[2]; |
14 | int result |
15 | LOG_ALWAYS_FATAL_IF(result!=0, "Could , 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 , |
22 | errno ); |
23 |
24 | result=fcntl(mWakeWritePipeFd,F_SETFL,O_NONBLOCK); |
25 | LOG_ALWAYS_FATAL_IF(result!=0, "Could , |
26 | errno ); |
27 |
28 | //Allocatetheepollinstanceandregisterthewakepipe. |
29 | mEpollFd=epoll_create(EPOLL_SIZE_HINT); |
30 | LOG_ALWAYS_FATAL_IF(mEpollFd<0, "Could , errno ); |
31 |
32 | struct epoll_event eventItem; |
33 | memset (&eventItem,0, sizeof (epoll_event)); // |
34 | eventItem.events=EPOLLIN; |
35 | eventItem.data.fd=mWakeReadPipeFd; |
36 | result=epoll_ctl(mEpollFd,EPOLL_CTL_ADD,mWakeReadPipeFd,& |
37 | LOG_ALWAYS_FATAL_IF(result!=0, "Could , |
38 | errno ); |
39 | } |
40 |
41 | void Looper::initTLSKey() { |
42 | int result |
43 | LOG_ALWAYS_FATAL_IF(result!=0, "Could ); |
44 | } |
45 |
46 | void Looper::threadDestructor( void *st) { |
47 | Looper* const self static_cast <Looper*>(st); |
48 | if (self |
49 | self->decStrong(( void *)threadDestructor); |
50 | } |
51 | } |
52 |
53 | void Looper::setForThread( const sp<Looper>& |
54 | sp<Looper>old=getForThread(); // |
55 |
56 | if (looper |
57 | looper->incStrong(( void *)threadDestructor); |
58 | } |
59 |
60 | pthread_setspecific(gTLSKey,looper.get()); |
61 |
62 | if (old |
63 | old->decStrong(( void *)threadDestructor); |
64 | } |
65 | } |
66 |
67 | sp<Looper>Looper::getForThread(){ |
68 | int result |
69 | LOG_ALWAYS_FATAL_IF(result!=0, "pthread_once failed" ); |
70 |
71 | return (Looper*)pthread_getspecific(gTLSKey); |
72 | } |
唤醒
然后来看当其他线程向Looper线程的MessageQueue中插入了消息时,Looper线程是如何被叫醒的。回忆我们前面看到的MessageQueue类的enqueueMessage()方法,它在最后插入消息之后,有调用一个nativeWake()方法。没错,正是这个nativeWake()方法执行了叫醒Looper线程的动作。那它又是如何叫醒Looper线程的呢?来看它的实现:view
source
01 | static void android_os_MessageQueue_nativeWake(JNIEnv* |
02 | NativeMessageQueue*nativeMessageQueue= reinterpret_cast <NativeMessageQueue*>(ptr); |
03 | return nativeMessageQueue->wake(); |
04 | } |
05 |
06 | //---------------------------------------------------------------------------- |
07 |
08 | static JNINativeMethod |
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 | }; |
view
source
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 errno ==EINTR); |
10 |
11 | if (nWrite |
12 | if ( errno != |
13 | ALOGW( "Couldnotwrite , errno ); |
14 | } |
15 | } |
16 | } |
休眠
接着是Looper线程休眠的过程。我们知道,Looper线程在Looper.loop()方法中,将会不断地从MessageQueue中取出消息,并处理。不难想象,休眠的时机应该是在取出消息的时候。由Looper.loop()方法的code,我们知道,它是通过MessageQueue.next()方法来从消息队列中取出消息的。我们来看MessageQueue.next()方法的实现:view
source
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 |
14 | MessageprevMsg= null ; |
15 | Messagemsg=mMessages; |
16 | if (msg null &&msg.target== null ) { |
17 | //Stalledbyabarrier.Findthenextasynchronous |
18 | do { |
19 | prevMsg=msg; |
20 | msg=msg.next; |
21 | } while (msg null &&!msg.isAsynchronous()); |
22 | } |
23 | if (msg null ){ |
24 | if (now |
25 | //Nextmessageisnotready.Setatimeout |
26 | nextPollTimeoutMillis=( int ) |
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 |
46 | if (mQuiting) { |
47 | dispose(); |
48 | return null ; |
49 | } |
50 |
51 | //Iffirsttimeidle,thengetthenumberofidlers |
52 | //Idlehandlesonlyrunifthequeueisemptyorif |
53 | //inthequeue(possiblyabarrier)isduetobehandled |
54 | if (pendingIdleHandlerCount 0 |
55 | &&(mMessages== null || |
56 | pendingIdleHandlerCount=mIdleHandlers.size(); |
57 | } |
58 | if (pendingIdleHandlerCount 0 ){ |
59 | //Noidlehandlerstorun.Loopandwaitsome |
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 |
72 | for ( int i 0 ;i<pendingIdleHandlerCount;i++){ |
73 | final IdleHandler |
74 | mPendingIdleHandlers[i]= null ; // |
75 |
76 | boolean keep false ; |
77 | try { |
78 | keep=idler.queueIdle(); |
79 | } catch (Throwable |
80 | Log.wtf( "MessageQueue" , "IdleHandler ,t); |
81 | } |
82 |
83 | if (!keep) { |
84 | synchronized ( this ) { |
85 | mIdleHandlers.remove(idler); |
86 | } |
87 | } |
88 | } |
89 |
90 | //Resettheidlehandlercountto0sowedonotrunthem |
91 | pendingIdleHandlerCount= 0 ; |
92 |
93 | //Whilecallinganidlehandler,anewmessagecouldhave |
94 | //sogobackandlookagainforapendingmessagewithout |
95 | nextPollTimeoutMillis= 0 ; |
96 | } |
97 | } |
view
source
01 | class MessageQueue public RefBase{ |
02 | public : |
03 | /*Getsthemessagequeue'slooper.*/ |
04 | inline sp<Looper> const { |
05 | return mLooper; |
06 | } |
07 |
08 | /*CheckswhethertheJNIenvironmenthasapendingexception. |
09 | * |
10 | *Ifanexceptionoccurred,logsittogetherwiththespecified |
11 | *andcallsraiseException()toensuretheexceptionwillbe |
12 | *thecallbackreturns,clearsthependingexceptionfromthe |
13 | *thenreturnstrue. |
14 | * |
15 | *Ifnoexceptionoccurred,returnsfalse. |
16 | */ |
17 | bool raiseAndClearException(JNIEnv* const char * msg); |
18 |
19 | /*Raisesanexceptionfromwithinacallbackfunction. |
20 | *Theexceptionwillberethrownwhencontrolreturnstothe |
21 | *willtypicallycausetheapplicationtocrash. |
22 | * |
23 | *Thismessagecanonlybecalledfromwithinacallbackfunction. |
24 | *atanyothertime,theprocesswillsimplybekilled. |
25 | * |
26 | *DoesnothingifexceptionisNULL. |
27 | * |
28 | *(Thismethoddoesnottakeownershipoftheexceptionobject |
29 | *Thecallerisresponsibleforreleasingitsreferencewhen |
30 | */ |
31 | virtual void raiseException(JNIEnv* const char * |
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* const char * |
47 |
48 | void pollOnce(JNIEnv* int timeoutMillis); |
49 |
50 | void wake(); |
51 |
52 | private : |
53 | bool mInCallback; |
54 | jthrowablemExceptionObj; |
55 | }; |
56 |
57 | void NativeMessageQueue::pollOnce(JNIEnv* 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* |
69 | jintptr,jinttimeoutMillis){ |
70 | NativeMessageQueue*nativeMessageQueue= reinterpret_cast <NativeMessageQueue*>(ptr); |
71 | nativeMessageQueue->pollOnce(env,timeoutMillis); |
72 | } |
view
source
001 | int Looper::pollOnce( int timeoutMillis, int * int *outEvents, void **outData){ |
002 | int result |
003 | for (;;) { |
004 | while (mResponseIndex |
005 | const Response& |
006 | int ident |
007 | if (ident |
008 | int fd |
009 | int events |
010 | void *data= |
011 | #ifDEBUG_POLL_AND_WAKE |
012 | ALOGD( "%p~pollOnce |
013 | "fd=%d,events=0x%x,data=%p" , |
014 | this , |
015 | #endif |
016 | if (outFd |
017 | if (outEvents |
018 | if (outData |
019 | return ident; |
020 | } |
021 | } |
022 |
023 | if (result |
024 | #ifDEBUG_POLL_AND_WAKE |
025 | ALOGD( "%p~pollOnce- , this ,result); |
026 | #endif |
027 | if (outFd |
028 | if (outEvents |
029 | if (outData |
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: , this ,timeoutMillis); |
040 | #endif |
041 |
042 | //Adjustthetimeoutbasedonwhenthenextmessageisdue. |
043 | if (timeoutMillis |
044 | nsecs_tnow=systemTime(SYSTEM_TIME_MONOTONIC); |
045 | int messageTimeoutMillis |
046 | if (messageTimeoutMillis |
047 | &&(timeoutMillis<0||messageTimeoutMillis<timeoutMillis)) { |
048 | timeoutMillis=messageTimeoutMillis; |
049 | } |
050 | #ifDEBUG_POLL_AND_WAKE |
051 | ALOGD( "%p~pollOnce-next , |
052 | this ,mNextMessageUptime |
053 | #endif |
054 | } |
055 |
056 | //Poll. |
057 | int result |
058 | mResponses.clear(); |
059 | mResponseIndex=0; |
060 |
061 | struct epoll_event eventItems[EPOLL_MAX_EVENTS]; |
062 | int eventCount |
063 |
064 | //Acquirelock. |
065 | mLock.lock(); |
066 |
067 | //Checkforpollerror. |
068 | if (eventCount |
069 | if ( errno == |
070 | goto Done; |
071 | } |
072 | ALOGW( "Pollfailedwithan , errno ); |
073 | result=ALOOPER_POLL_ERROR; |
074 | goto Done; |
075 | } |
076 |
077 | //Checkforpolltimeout. |
078 | if (eventCount |
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 , this ,eventCount); |
089 | #endif |
090 |
091 | for ( int i |
092 | int fd |
093 | uint32_tepollEvents=eventItems[i].events; |
094 | if (fd |
095 | if (epollEvents |
096 | awoken(); |
097 | } else { |
098 | ALOGW( "Ignoringunexpected ,epollEvents); |
099 | } |
100 | } else { |
101 | ssize_trequestIndex=mRequests.indexOfKey(fd); |
102 | if (requestIndex |
103 | int events |
104 | if (epollEvents |
105 | if (epollEvents |
106 | if (epollEvents |
107 | if (epollEvents |
108 | pushResponse(events,mRequests.valueAt(requestIndex)); |
109 | } else { |
110 | ALOGW( "Ignoringunexpected |
111 | "nolongerregistered." , |
112 | } |
113 | } |
114 | } |
115 | Done:; |
116 |
117 | //Invokependingmessagecallbacks. |
118 | mNextMessageUptime=LLONG_MAX; |
119 | while (mMessageEnvelopes.size() |
120 | nsecs_tnow=systemTime(SYSTEM_TIME_MONOTONIC); |
121 | const MessageEnvelope& |
122 | if (messageEnvelope.uptime |
123 | //Removetheenvelopefromthelist. |
124 | //Wekeepastrongreferencetothehandleruntilthe |
125 | //finishes.Thenwedropitsothatthehandlercan |
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 , |
136 | this , |
137 | #endif |
138 | handler->handleMessage(message); |
139 | } //releasehandler |
140 |
141 | mLock.lock(); |
142 | mSendingMessage= false ; |
143 | result=ALOOPER_POLL_CALLBACK; |
144 | } else { |
145 | //Thelastmessageleftattheheadofthequeuedetermines |
146 | mNextMessageUptime=messageEnvelope.uptime; |
147 | break ; |
148 | } |
149 | } |
150 |
151 | //Releaselock. |
152 | mLock.unlock(); |
153 |
154 | //Invokeallresponsecallbacks. |
155 | for ( size_t i |
156 | Response&response=mResponses.editItemAt(i); |
157 | if (response.request.ident |
158 | int fd |
159 | int events |
160 | void *data=response.request.data; |
161 | #ifDEBUG_POLL_AND_WAKE||DEBUG_CALLBACKS |
162 | ALOGD( "%p~pollOnce- , |
163 | this ,response.request.callback.get(), |
164 | #endif |
165 | int callbackResult |
166 | if (callbackResult |
167 | removeFd(fd); |
168 | } |
169 | //Clearthecallbackreferenceintheresponsestructure |
170 | //willnotcleartheresponsevectoritselfuntilthe |
171 | response.request.callback.clear(); |
172 | result=ALOOPER_POLL_CALLBACK; |
173 | } |
174 | } |
175 | return result; |
176 | } |
Done。
转载自
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories