2 Studying《Android源代码情景分析(罗升阳)》
目录
1 Android应用程序的消息处理机制(MessageQueue,Looper,Handler)
1.1 创建线程消息队列 Looper
1.2 线程消息循环过程 Looper
1.3 线程消息发送过程 Handler
1.4 线程消息处理过程 Handler
2 Android系统广播机制(Broadcast Receiver)
2.1 广播机制应用实例
2.2 广播接收者的注册过程
2.3 广播的发送与处理过程
3 Android应用程序的线程消息循环模型(ActivityThread,HandlerThread,AsyncThread)
3.1 应用程序主线程消息循环模型ActivityThread
3.2 与界面无关的应用程序子线程消息循环模型HandlerThread
3.3 与界面相关的应用程序子线程消息循环模型AsyncThread
1 Android应用程序的消息处理机制(MessageQueue,Looper,Handler)
Android应用程序是通过消息驱动的。应用程序的每个线程启动时,会在内部创建一个消息队列,然后再进入到一个无限循环中。如果有新的消息需要处理,那么线程就会将它从消息队列中取出来处理;否则,线程进入睡眠状态,直到有新的消息需要处理为止。
Android系统主要通过MessageQueue,Looper和Handler三个类来实现Android应用程序的消息处理。MessageQueue类用来描述消息队列,Looper类用来创建消息队列,进入消息循环;Handler类用来发送消息和处理消息。
1.1 创建线程消息队列 Looper
MessageQueue对象可以通过Looper类的静态成员函数prepareMainLooper或prepare来创建,其中,prepareMainLooper用来为应用程序的主线程创建消息队列,prepare用来为应用程序的子线程创建消息队列。
类图如下:
Java层中的MessageQueue对象的成员变量mPtr,保存了C++层中NativeMessageQueue对象的地址,这样Java层MessageQueue对象和C++层NativeMessageQueue对象就联系起来了。
Looper[Native]对象的成员变量mWakeReadPipedFd和mWakeWritePipedFd,分别表示一个管道的读端文件描述符和写端文件描述符。当一个线程的消息队列没有消息需要处理时,它就会在这个管道的读端文件描述符上进行睡眠等待,直到其他线程通过这个管道的写端文件描述符来唤醒它为止。
顺序图如下:
分析线程消息队列的创建过程,即分析Looper类的静态成员函数prepareMainLooper和prepare的实现。
frameworks/base/core/java/android/os/Looper.java
public class Looper {......private static final ThreadLocal sThreadLocal = new ThreadLocal();final MessageQueue mQueue;private static Looper mMainLooper = null;......public static final void prepare() {if (sThreadLocal.get() != null) {throw new RuntimeExcepition("Only one looper may be created per thread");}sThreadLocal.set(new Looper());}public static final void prepareMainLooper() {prepare();setMainLooper(myLooper());......}private synchronized static void setMainLooper(Looper looper) {mMainLooper = looper;}public synchronized static final Looper getMainLooper() {return mMainLooper;} public static final Looper myLooper() {return (Looper)sThreadLocal.get();}......
}
Looper类的静态成员变量sThreadLocal,可以理解为一个线程局部变量,关联一个Looper对象。
Looper类的静态成员函数prepareMainLooper只能在Android应用程序主线程(UI线程)中调用。将主线程Looper对象保存在一个独立的静态成员变量中,是为了让其他线程可以通过Looper类的静态成员函数getMainLooper()来访问它,从而可以向它的消息队列中发送一些与UI操作相关的消息。
Looper对象的创建过程中,会在内部创建一个MessageQueue对象。
frameworks/base/core/java/android/os/Looper.java
public class Looper {private Looper() {mQueue = new MessageQueue();......}
}
一个MessageQueue对象在创建过程中,又会在C++层创建NativeMessageQueue对象。
frameworks/base/core/java/android/os/MessageQueue.java
public class MessageQueue {private int mPtr;private native void nativeInit();MessageQueue() {nativeInit();}
}
frameworks/base/core/jni/android_os_MessageQueue.cpp
static struct {jclass clazz;jfieldID mPtr;
} gMessageQueueClassInfo;static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();......android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
}static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj, NativeMessageQueue* nativeMessageQueue) {env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr, reinterpret_cast<jint>(nativeMessageQueue));
}NativeMessageQueue::NativeMessageQueue() {mLooper = Looper::getForThread();if (mLooper == NULL) {mLooper = new Looper(false);Looper::setForThread(mLooper);}
}
android_os_MessageQueue_setNativeMessageQueue将nativeMessageQueu与Java层的MessageQueue对象关联起来。
gMessageQueueClassInfo的clazz指向Java层的MessageQueue类,mPtr指向MessageQueue类的mPtr成员。
一个NativeMessageQueue对象在创建时又会创建一个C++层的Looper对象。getForThread用来检查是否已经为当前线程船舰过一个C++层的Looper对象。setForThread用来将C++层Looper对象与线程关联起来。
一个C++层的Looper对象在创建的过程中,又会在内部创建一个管道。
frameworks/base/libs/utils/Looper.cpp
Looper::Looper(bool allowNonCallbacks) :mAllowNonCallbacks(allowNonCallbacks),mResponseIndex(0) {int wakeFds[2];int result = pipe(wakeFds);......mWakeReadPipeFd = wakeFds[0];mWakeWritePipeFd = wakeFds[1];......// Allocate the epoll instance and registermEpollFd = epoll_create(EPOLL_SIZE_HINT);......struct epoll_event eventItem;memset(&eventItem, 0, sizeof(epoll_event));eventItem.events = EPOLLIN;eventItem.data.fd = mWakeReadPipeFd;result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);......
}
当一个线程没有新消息需要处理时,它就会睡眠在这个管道的读端文件描述符上,直到新的消息到来为止;当其他线程像这个线程的消息队列发送了一个消息后,其他线程就会通过这个管道的写端文件描述符向这个管道写入一个数据,从而将这个线程唤醒。
IO多路复用epoll机制适用于监听了大量的文件描述符,但某一时刻只有少数文件描述符是活跃的情况。这里只监听了一个文件描述符,值得使用epoll机制么?实际上,我们还可以调用Looper类的成员函数addFd向这个epoll实例中注册更多的文件描述符,以便可以监听它们的IO读写事件。如Android应用程序的键盘消息处理机制等。
1.2 线程消息循环过程 Looper
顺序图如下:
(1)Looper.loop
frameworks/base/core/java/android/os/Looper.java
public class Looper {public static final void loop() {Looper me = myLooper();MessageQueue queue = me.mQueue;......while (true) {// might blockMessage msg = queue.next();......if (msg != null) {......}}}
}
(2)MessageQueue.next
frameworks/base/core/java/android/os/MessageQueue.java
public class MessageQueue {......final Message next() {int pendingIdleHandleCount = -1;int nextPollTimeoutMillis = 0;for(;;) {if (nextPollTimeoutMillis != 0) {Binder.flushPendingCommands();}nativePollOnce(mPtr, nextPollTimeoutMillis);synchronized (this) {// Try to retrieve the next message. Return if foundfinal long now = SystemClock.uptimeMillis();final Message msg = mMessages;if (msg != null) {final long when = msg.when;if (now >= when) {......mMessages = msg.next;msg.next = null;......return msg;} else {nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);}} else {nextPollTimeoutMillis = -1;}......// Get the idle handlers......}// Run the idle handles......// While calling an idle handle, a new message could have been delivered// so go back and look again for a pending message without waitingnextPollTimeoutMillis = 0;}}
}
变量pendingIdleHandleCount用来保存注册到消息队列中的空闲消息处理器(idle handlers)的个数。
变量nextPollTimeoutMillis用来描述当消息队列中没有新的消息需要处理时,当前线程需要睡眠等待的时间。nextPollTimeoutMillis=x,表示要睡眠x时间。nextPollTimeoutMillis=0,表示线程不会进入睡眠。nextPollTimeoutMillis=-1,表示线程需要无限处于睡眠状态,直到被其他线程唤醒。
nextPollTimeoutMillis!=0,说明当前线程会在nativePollOnce中睡眠等待,Binder.flushPendingCommands用来处理那些正在等待处理的Binder间进程通信请求,避免它们长时间得不到处理。
nativePollOnce函数来检查当前线程的消息队列中是否有新的消息需要处理。
MessggeQueue类的成员变量mMessages描述消息的处理时间。当nativePollOnce函数执行完成后,如果有新的消息需要处理,则mMessage不等于null。
如果消息的处理时间小于等于系统的当前时间,说明当前线程需要马上对其进行处理;否则,当前线程进入睡眠等待,以在指定的时间对消息进行处理。每一个发送到消息队列的消息是按照它们的处理时间从小到大的顺序排列在消息队列里的。
当前线程进入睡眠前,会分发一个线程空闲消息给idle handlers处理。
(3)MessageQueue.nativePollOnce
frameworks/base/core/jni/android_os_MessageQueue.cpp
static void android_os_MessageQueue_nativePollOnce(JNIEnv *env, jobject obj, jnit ptr, jint timeoutMillis) {NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);nativeMessageQueue->pollOnce(timeoutMillis);
}
(4)NativeMessageQueue.pollOnce
frameworks/base/core/jni/android_os_MessageQueue.cpp
void NativeMessageQueue::pollOnce(int timeoutMillis) {mLooper->pollOnce(timeoutMillis);
}
(5)Looper.pollOnce
frameworks/base/libs/utils/Looper.cpp
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {for(;;) {......if (result != 0) {return result;}result = pollInner(timeoutMillis);}
}
如果有新的消息需要处理,pollInner函数返回值不为0。
(6)Looper.pollInner
frameworks/base/libs/utils/Looper.cpp
int Looper::pollInner(int timeoutMillis) {......int result = ALOOPER_POLL_WAKE;......struct epoll_event eventItems[EPOLL_MAX_EVENTS];int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);......for (int i = 0; i < eventCount; i++) {int fd = eventItem[i].data.fd;uint32_t epollEvents = eventItems[i].events;if (fd == mWakeReadPipeFd) {if (epollEvents & EPOLLIN) {awoken();}......}......} ......return result;
}
在"1 创建线程消息队列 Looper"中,我们创建了以个epoll实例,并将fd保存在mEpollFd中。
epoll_wait用来监听注册在epoll实例中的文件描述符的读写事件。如果这些文件描述符都没有发生IO读写事件,那么当前线程会在epoll_wait中进入睡眠等待,等待的时间由timeoutMillis指定。
awoken()函数将与当前线程关联的一个管道数据读出来,以便当前线程下一次可以重新在这个管道上等待其他线程向它的消息队列发送一个新的消息。
(7)Looper.awoken
frameworks/base/libs/utils/Looper.cpp
void Looper::awoken() {......char buffer[16];ssize_t nRead;do {nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));......} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
}
1.3 线程消息发送过程 Handler
类图如下:
一般使用Handler类的默认构造函数来创建一个Handler对象,初始化mLooper和mQueue对象。
frameworks/base/core/java/android/os/Handler.java
public class Handler {public Handler() {......mLooper = Looper.myLooper();mQueue = mLooper.mQueue;}......final MessageQueue mQueue;final Looper mLooper;
}
从sendMessage函数开始分析线程消息发送过程。
顺序图如下:
(1)Handler.sendMessage
frameworks/base/core/java/android/os/Handler.java
public class Handler {......public final boolean sendMessage(Message msg){ return sendMessageDelayed(msg, 0);}public final boolean sendMessageDelayed(Message msg, long delayMillis){if (delayMillis < 0) {delayMillis = 0;}return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}public boolean sendMessageAtTime(Message msg, long uptimeMillis){boolean sent = false;MessageQueue queue = mQueue;if (queue != null) {msg.target = this;sent = queue.enqueueMessage(msg, uptimeMillis);}......return sent;}
}
将msg的成员变量target设置为当前正在处理的Handler对象,发送出去。
(2)MessageQueue.enqueueMessage
frameworks/base/core/java/android/os/MessageQueue.java
public class MessageQueue {final boolean enqueueMessage(Message msg, long when) {......final boolean needWake;synchronized (this) {......msg.when = when;Message p = mMessages;if (p == null || when == 0 || when < p.when) {msg.next = p;mMessages = msg;// new head, might need to wake upneedWake = mBlocked;} else {Message prev = null;while (p!=null && p.when < = when) {prev = p;p = p.next;}msg.next = prev.next;prev.next = msg;// still waiting on head, no need to wake upneedWake = false;}}if (needWake) {nativeWake(mPtr);}return true;}
}
消息队列中的消息是按照它们的处理时间从小到大的顺序来排列的,分四种情况来讨论将一个消息插入到一个目标消息队列中。
(1)目标消息队列是一个空队列。
(2)插入的消息处理时间为0。
(3)插入的消息处理时间小于保存在目标消息队列头的消息处理时间。
(4)插入的消息处理时间大于等于保存在目标消息队列头的消息处理时间。
其中:
(4)将插入的消息保存在目标消息队列中间,因为头部消息没有发生变化,当前线程不需要对目标线程执行唤醒操作,needWake=false。
(1)~(3)将插入的消息保存在目标消息队列头部,因为头部消息发生变化,当前线程需要将目标线程唤醒,以便它可以对保存在目标消息队列头部的新消息进行处理。如果这时目标线程不是正处于睡眠状态,则不需要唤醒。成员变量mBlocked记录了目标线程是否处于睡眠状态。true表示目标线程处于睡眠状态。
(3)MessageQueue.nativeWake
frameworks/base/core/jni/android_os_MessageQueue.cpp
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jnit ptr) {NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);return nativeMessageQueue->wake();
}
wake唤醒目标线程
(4)NativeMassageQueue.wake
frameworks/base/core/jni/android_os_MessageQueue.cpp
void NativeMessageQueue::wake() {mLooper->wake();
}
(5)Looper.wake
frameworks/base/libs/utils/Looper.cpp
void Looper::wake() {......ssize_t nWrite;do {nWrite = write(mWakeWritePipeFd, "W", 1);} while (nWrite == -1 && errno == EINTR);......
}
write函数写的过程中如果中断,则返回-1,同时errno置为EINTR。
write函数向管道写端文件描述符写入了一个"W"字符,这时目标线程会因为管道发生了一个IO写事件而被唤醒。
1.4 线程消息处理过程 Handler
由"2 线程消息循环过程 Looper"知道,当线程没有新消息需要处理是,会在pollInner中进入睡眠;当这个线程有新消息处理时,它会在pollInner中被唤醒,然后沿着之前的调用路径返回到Java层的loop函数中,我们从loop函数分析一个线程的消息处理过程。
顺序图如下:
(1)Looper.loop
frameworks/base/core/java/android/os/Looper.java
public class Looper {......public static final void loop() {Looper me = myLooper();MessageQueue queue = me.mQueue;......while (true) {// might blockMessage msg = queue.next();......if (msg != null) {if (msg.target == null) {// for the quit messagereturn;}......msg.target.dispatchMessage(msg);}}}
}
判断msg.target是否为null,如果为null,说明要处理的是一个退出消息。
由"3 线程消息发送过程 Handler"可知,msg.target指向的是一个Handler对象,继续分析。
(2)Handler.dispatchMessage
frameworks/base/core/java/android/os/Handler.java
public class Handler {......public void dispatchMessage(Message msg) {if (msg.callback != null) {handleCallback(msg);} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}......final Callback mCallback;
}
Handler类的dispatchMessage函数按照以下顺序分发消息:
(1)要处理的消息发送时指定了一个回调时,用Handler类的handleCallback函数来处理。
(2)Handler类的成员mCallback指向一个回调时,用mCallback.handleMessage函数来处理。
(3)上述条件都不成立的话,最后用Handler类的handleMessage函数来处理。
分析这三种情况:
[1]Handler类的handleCallback函数
frameworks/base/core/java/android/os/Handler.java
public class Handler {private final void handleCallback(Message message) {message.callback.run();}public final boolean post(Runnable r){return sendMessageDelayed(getPostMessage(r), 0);}private final Message getPostMessge(Runnable r) {Message m = Message.obtain();m.callback = r;return m;}
}
message.callback指向的是一个Runnable对象。
要处理的消息是什么时候指定了一个回调呢?是调用post的时候。
[2]Handler类内部定义Callback接口
frameworks/base/core/java/android/os/Handler.java
public class Handler {public Handler(Callback callback){mLooper = Looper.myLooper();......mCallback = callback; }public interface Callback{public boolean handleMessage(Message msg);}
}
第3种情况如下:
(3)Handler.handleMessage
frameworks/base/core/java/android/os/Handler.java
public class Handler {// Subclass must implement this to receive messagespublic void handleMessage(Message msg) {}
}
Handler类的handleMessage实现是空的,一般子类重写了父类的handleMessage函数来处理消息。
线程消息的处理过程分析完毕,这些消息都是先发送到一个消息队列,然后从这个消息队列中取出来处理。
还有一种特殊的消息,是在线程空闲的时候处理的,称为线程空闲消息。线程空闲消息是由空闲消息处理器的对象来处理的,空闲消息处理器必须要实现IdleHandler接口。
frameworks/base/core/java/android/os/MessageQueue.java
public class MessageQueue {....../* Return true to keep your idle handler active,false to have it removed.* Called when the message queue has run out of messages and will now wait for more.* Or may be called if there are still messages pending in the queue,* but they are all scheduled to be dispatched after the current time.*/public static interface IdleHandler {boolean queueIdle();}public final void addIdleHandler(IdleHandler handler) {if (handler == null) {throw new NullPointerExcepition("Can't add a null IdleHandler");}synchronized(this) {mIdleHandlers.add(handler);}}public final void removeIdleHandler(IdleHandler handler) {syschronized(this) {mIdleHandlers.remove(handler);}}
}
queueIdle函数用来接收线程空闲消息。
变量mIdleHandlers指向一个IdleHandler列表,用来保存一个线程的空闲消息处理器。函数addIdleHandler和removeIdleHandler用来注册和注销一个空闲消息处理器。
当一个线程的消息队列为空,或保存在消息队列头部的消息的处理时间大于系统的当前时间时,线程处于一种空闲状态,接下来它会进入睡眠状态。在进入睡眠状态前,线程会发出线程空闲消息给那些注册了的空闲消息处理器来处理。
frameworks/base/core/java/android/os/MessageQueue.java
public class MessageQueue {......final Message next() {int pendingIdleHandleCount = -1;......for(;;) {......nativePollOnce(mPtr, nextPollTimeoutMillis);synchronized (this) {// Get the idle handlers......if (pendingIdleHandleCount < 0) {pendingIdleHandleCount = mIdleHandlers.size();}......if (pendingIdleHandleCount == 0) {continue;}if (mPendingIdleHandlers == null) {mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandleCount, 4)];}mIdleHandlers.toArray(mPendingIdleHandlers);}// Run the idle handlesfor (int i=0; i < pendingIdleHandlerCount; i++) {final IdleHandler idler = mPendingIdleHandlers[i];// release the reference to the handlermPendingIdleHandlers[i] = null;boolean keep = false;try {keep = idler.queueIdle();} catch (Throwable t) {Log.wtf("MessageQueue", "IdleHandler threw exception", t);}if (!keep) {synchonized (this) {mIdleHandlers.remove(idler);}}}// Reset the idle handler count to 0 so we do not run them againpendingIdleHandlerCount = 0;}}
}
只有两种情况下pendingIdleHandleCount等于0,一种情况是没有空闲消息处理器注册到当前线程的消息队列中;一种情况是之前已经发送过一个线程空闲消息了(queueIdle())。
可以看出,在next()的一次调用中,一个线程最多只会发出一个线程空闲消息。
通过注册空闲消息处理器,可以把不紧急的事情放到线程空闲的时候执行,充分利用线程的空闲时间。
2 Android系统广播机制(Broadcast Receiver)
广播(Broadcast)是一种在组件之间进行消息传递的方式。这些组件可以运行在同一个进程中,也可以在不同的进程中。事实上,广播机制就是在Binder进程间通信的基础上实现的。那么,有了Binder通信Android系统为什么还需要广播机制呢?在Binder通信时,Client端在和Server端通信前要先获得Server端的一个代理。而在广播中,发送者是不需要知道接收者是否存在的,这降低了发送者和接收者之间的耦合度。所以Android系统需要广播机制。
Android系统将广播接收者抽象为一种Broadcast Receiver组件,是Android应用程序的四大组件之一。另外两种组件,Activity组件和Service组件被赋予了发送广播的能力。广播机制存在一个注册中心,由ActivityManagerService来担当。广播接收者会先将自己注册到AMS中,并指定要接收的广播的类型。当广播发送者发送一个广播时,先发送到AMS,然后AMS根据广播类型找到对应的广播接收者,最后将广播发送给接收者处理。
广播接收者的注册方式分为静态注册和动态注册两种。静态注册中,需要在配置文件AndroidManifest.xml注明它们感兴趣的广播类型,以便AMS可以找到它们。动态注册中,需要调用Context接口的成员函数registerReceiver将Broadcast Receiver组件注册到AMS中。动态注册的广播接收者的优先级高于静态注册的广播接收者。
广播的发送分为有序和无序两种。注册广播时可以指定它们的优先级,当AMS接收到有序广播时,AMS会按照优先级将广播发送给接收者处理;当AMS接收到无序广播时,忽略优先级将广播发送给接收者处理。
2.1 广播机制应用实例
Broadcounter应用程序
ICounterService.java
public interface ICounterService {public void startCounter(int initVal);public void stopCounter();
}
CounterService.java
public class CounterService extends Service implements ICounterService {public final static String BROADCAST_COUNTER_ACTION = "broadcounter.COUNTER_ACTION";public final static String COUNTER_VALUE = "broadcounter.counter.value"......public void startCounter(int initVal) {AsyncTask<Integer, Integer, Integer> task = new AsyncTask<Integer, Integer, Integer>() {@Overrideprotected Integer doInBackground(Integer... vals) {Integer initCounter = vals[0];stop = false;while (!stop) {// 每隔1s计数器+1publishProgress(initCounter);try {Thread.sleep(1000);} catch (InterruptedExcepiton e) {e.printStackTrace();}initCounter++;}return initCounter;} @Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);int counter = values[0];Intent intent = new Intent(BROADCAST_COUNTER_ACTION);intent.putExtra(COUNTER_VALUE, counter);sendBroadcast(intent);}@Overrideprotected void onPostExecute(Integer val) {int counter = val;Intent intent = new Intent(BROADCAST_COUNTER_ACTION);intent.putExtra(COUNTER_VALUE, counter);sendBroadcast(intent);}};task.execute(initVal);}public void stopCounter() {stop = true;}
}
通过异步任务AsyncTask来提供计数器功能,通过CounterService父类ContextWrapper的成员函数sendBroadcast发送广播,以便Broadcounter组件可以接收到这个广播,获取计数值。
Broadcounter.java
public class Broadcounter extends Activity implements OnClickListener {@Overridepublic void onResume() {super.onResume();IntentFilter counterActionFilter = new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION);registerReceiver(counterActionReceiver, counterActionFilter);}@Overridepublic void onPause() {super.onPause();unregisterReceiver(counterActionReceiver);}private BroadcastReveiver counterActionReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);String text = String.valueOf(counter);counterText.setText(text);}};
}
Broadcounter组件定义了一个广播接收者counterActionReceiver,它用来接收类型为BROADCAST_COUNTER_ACTION的广播,以便计算当前计数值。
Broadcounter组件激活时,调用父类ContextWrapper的registerReceiver函数将广播接收者counterActionReceiver注册到AMS中。
Broadcounter组件被中止时,调用父类ContextWrapper的unregisterReceiver函数将广播接收者counterActionReceiver从AMS中注销。
编译:
mmm ./packages/experimental/Broadcouner
/out/target/product/generic/system/app生成Broadcouner.apk
打包:
make snod
/out/target/product/generic生成system.img
测试:
emulator
2.2 广播接收者的注册过程
广播接收者的注册过程如下:
图2 广播接收者的注册过程
(1)Broadcounter.onResume
packages/experimental/.../Broadcounter.java
public class Broadcounter extends Activity implements OnClickListener {@Overridepublic void onResume() {super.onResume();IntentFilter counterActionFilter = new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION);registerReceiver(counterActionReceiver, counterActionFilter);}...... private BroadcastReveiver counterActionReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);String text = String.valueOf(counter);counterText.setText(text);}};
}
要接收的广播类型为BROADCAST_COUNTER_ACTION。
(2)ContextWrapper.registerReceiver
frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {Context mBase;......@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {return mBase.registerReceiver(receiver, filter);}
}
mBase指向一个ContextImpl对象。
(3)ContextImpl.registerReceiver
frameworks/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {// 默认包访问控制/*package*/ LoadedApk mPackageInfo;/*package*/ ActivityThread mMainThread;private Context mOuterContext;......@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {return registerReceiver(receiver, filter, null, null);}@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,String broadcastPermisssion, Handler scheduler) {return registerReceiverInternal(receiver, filter, broadcastPermission, scheduler, getOuterContext());}private Intent registerReceiverInternal(BroadcastReceiver receiver, IntentFilter filter,String broadcastPermisssion, Handler scheduler, Context context) {IIntentReceiver rd = null;if (receiver != null) {if (mPackageInfo != null && context != null) {if (scheduler == null) {scheduler = mMainThread.getHandler();}rd = mPackageInfo.getReceiverDispatcher(receiver, context, scheduler, mMainThread.getInstrumentation(), true);}......}try {return ActivityManagerNative.getDefault().registerReceiver(mMainThread.getApplicationThread(), rd, filter, broadcastPermission);} catch (RemoteException e) {return null;}}
}
getReceiverDispatcher函数将广播接收者receiver封装成一个实现了IIntentReceiver接口的Binder本地对象rd。
ActivityManagerNative.getDefault()返回AMS的代理对象。registerReceiver函数将Binder本地对象rd,IntentFilter对象等信息发送给AMS,AMS可以将rd注册在内部,将IntentFilter对象描述的广播转发处理。
成员mMainThread用来描述当前应用程序进程的,getHandler()返回的Handler对象用来向进程主线程的消息队列发送消息。一个广播到达对应的广播接收者应用程序进程时,首先会封装成一个消息,然后再发送到该应用程序进程主线程的消息队列中,最后才会分发给广播接收者处理。
getOuterContext()返回的是成员mOuterContext,指向的是一个Activity组件,这里是指Broadcounter组件。这样registerReceiverInternal就把广播接收者receiver和Broadcouner组件联系到了一起。
frameworks/base/core/java/android/app/LoadedApk.java
final class LoadedApk {public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler,Instrumentation instrumentation, boolean registered) {synchronized (mReceivers) {// rd是RevevierDispatcher的缩写LoadedApk.ReceiverDispatcher rd = null;HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;if (registered) {map = mReceivers.get(context);if (map != null) {rd = map.get(r);}}if (rd == null) {rd = new ReceiverDispatcher(r, context, handler, instrumentation, registered);if (registerd) {if (map == null) {map = new HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();mReceivers.put(context, map);}}} else {rd.validate(context, handler);}return rd.getIIntentReceiver();}} ...
}
每一个注册过广播接收者的Activity组件在LoadedApk类中都有一个对应的ReceiverDispatcher对象,它负责将这个被注册的广播接收者与Acitivity组件关联在一起。LoadedApk.ReceiverDispatcher通过map与BroadcastReceiver关联,map通过mReceivers与Activity组件的context关联。
rd.getIIntentReceiver()用来获得一个实现了IIntentReceiver接口的Binder本地对象。
frameworks/base/core/java/android/app/LoadApk.java
final class LoadedApk {static final class ReceiverDispatcher {final static class InnerReceiver extends IIntentReceiver.Stub {final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;......InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {mDispatcher = new WeakReferance<LoadedApk.ReceiverDispatcher>(rd);......}}......final IIntentReceiver.Stub mIIntentReceiver;final BroadcastReceiver mReceiver;final Context mContext;final Handler mActivityThread;......ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered) {......mIIntentReceiver = new InnerReceiver(this, !registered);mReceiver = receiver;mContext = context;mActivityThread = activityThread;......}IIntentReceiver getIIntentReceiver() {return mIIntentReceiver;}}
}
弱引用mDispatcher指向了一个外部的ReceiverDispatcher对象。
mIIntentReceiver指向一个实现了IIntentReceiver接口的本地对象。mContext指向了一个Activity组件,mActivityThread和mReceiver分别指向了与该Activity组件相关联的一个Handler对象和一个广播接收者。例如,Broadcounter组件在注册广播接收者counterActionReceiver时,LoadedApk类会为它创建一个ReceiverDispatcher对象,这个对象的成员mContext,mReceiver和mActivityThread分别指向了Broadcounter组件,Broadcounter组件的广播接收者counterActionReceiver和Broadcounter组件所在进程的主线程的一个Handler对象。
回到ContextImpl的registerReceiverInternal中,它将广播接收者receiver封装成一个InnerReceiver对象后,将这个InnerReceiver对象注册到AMS中了。
(4)ActivityMangerProxy.registerReceiver
frameworks/base/core/java/android/app/ActivityManagerNative.java
class ActivityManagerProxy implements IActivityManager {public IIntent registerReceiver(IApplicationThread caller, IIntentReceiver receiver, IntentFilter filter, String perm) throws RemoteException {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManger.descriptor);data.writeStrongBinder(caller != null ? caller.asBinder() : null);data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);filter.writeToParcel(data, 0);data.writeString(perm);mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);reply.readExceptinon();Intent intent = null; int haveIntent = reply.readInt();if (haveIntent != 0) {intent = Intent.CREATOR.createFromParcel(reply);}reply.recycle();data.recycle();return intent;}......
}
mRemote是ActivityManagerProxy类内部的一个Binder代理对象。
以上4步都是在应用程序Broadcounter中执行的,下面第5步是在AMS中执行的。
(5)ActivityMangerService.registerReceiver
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNatice implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {public Intent registerReceiver(IApplicationThread caller, IIntentReceiver receiver, IntentFilter filter, String permission) {sychonized(this) {ProcessRecord callerApp = null;if (caller != null) {callerApp = getRecordForAppLocked(caller);......}List allSticky = null;// Look for any matching sticky broadcasts...Iterator actions = filter.actionsIterator();if (actions != null) {while (actions.hasNext()) {String action = (String)actions.next();allSticky = getStickiesLocked(action, filter, allSticky);}}......// The first sticky in the list is returned directly back to the clientIntent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;......ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());if (rl == null) {rl = new ReceiverList(this, callerApp, Binder.getCallingPid(), Binder.getCallingUid(), receiver);......mRegisteredReceiver.put(receiver.asBinder(), rl);}BroadcastFiler bf = new BroadcastFiler(filter, rl, permission);rl.add(bf);mReceiverResolver.addFiler(bf);......return sticky;}}......
}
AMS的registerReceiver函数用来处理类型为REGISTER_RECEIVER_TRANSACTION的进程间通信请求。
ProcessRecord对象callerApp,用来描述正在请求AMS注册广播接收者的一个Activity组件所运行的应用程序进程。
sticky broadcast:什么是黏性广播呢?一个黏性广播被发送到AMS后,就会一直保存在AMS中,直到AMS下次再接收到同类型的黏性广播为止。一个Activity组件在向AMS注册广播时,如果AMS内部恰好保存这种类型的黏性广播,那么AMS会将这个黏性广播返回给这个Activity组件,以便可以知道上一次广播的内容。可以通过Activity组件或Service组件的父类ContextWrapper的sendStickyBroadcast向AMS发送一个黏性广播。
当AMS接收到一个广播时,它就会根据这个广播的类型在内部(mReceiverResolver)找到对应的InnerReceiver对象,然后再通过此InnerReceiver对象将这个广播发送给对应的广播接收者处理。
2.3 广播的发送与处理过程
(1)(2)发送,(3)(4)处理:
(1)广播发送者,即一个Activity组件或一个Service组件,将一个特定类型的广播发送给AMS。
(2)AMS接收到一个广播后,首先找到与这个广播对应的广播接收者,然后将它们添加到一个广播调度队列里,最后向AMS所在的线程的消息队列发送一个类型为BROADCAST_INTENT_MSG的消息。这时候对广播发送者来说,一个广播就发送完了。
(3)当AMS所在线程的消息队列中的BROADCAST_INTENT_MSG消息被处理时,AMS就会从广播调度队列里找到需要接收广播的广播接收者,并且将广播发送到广播接收者所运行的应用程序进程。
(4)广播接收者运行的应用程序进程接收到AMS发送过来的广播后,并不是直接处理,而是将广播封装成一个消息发送到主线程的消息队列中。当等到这个消息被处理时,应用程序进程再处理。
图3 广播的发送处理过程(1-4)
(1)CounterService.startCounter
package/experimental/Broadcounter/.../CounterService.java
public class CounterService extends Service implements ICounterService {public void startCounter(int initVal) {AsyncTask<Integer, Integer, Integer> task = new AsyncTask<>() {......@Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);int counter = values[0];Intent intent = new Intent(BROADCAST_COUNTER_ACTION);intent.putExtra(COUNTER_VALUE, counter);sendBroadcast(intent);}@Overrideprotected void onPostExecute(Integer val) {int counter = val;Intent intent = new Intent(BROADCAST_COUNTER_ACTION));intent.putExtra(COUNTER_VALUE, counter);sendBroadcast(intent);}};task.execute(initVal);}......
}
异步任务AsyncTask
(2)ContextWrapper.sendBroadcast
frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {Context mBase;......@Overridepublic void sendBroadcast(Intent intent) {mBase.sendBroadcast(intent);}
}
mBase指向ContextImpl对象。
(3)ContextImpl.sendBroadcast
frameworks/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {......@Overridepublic void sendBroadcast(Intent intent) {String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());try {ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(), intent, resolvedType, null,Activity.RESULT_OK, null, null, null, false ,false);} catch (RemoteException e) {}}
}
AMS的代理对象类型ActivityManagerProxy。
(4)ActivityManagerProxy.broadcastIntent
frameworks/base/core/java/android/app/ActivityManagerNative.java
class ActivityManagerProxy implements IActivityManager {public int broadcastIntent(IApplicationThread caller,Intent intent, String resolvedType, IIntentReceiver resultTo,int resultCode, String resultData, Bundle map,String requiredPermission, boolean serialized, boolean sticky) throws RemoteException{Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManager.descriptor);data.writeStrongBinder(caller != null ? caller.asBinder() : null);intent.writeToParcel(data, 0);data.writeString(resolvedType);data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);...mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);...}
}
向AMS发送一个BROADCAST_INTENT_TRANSACTION的进程间通信请求,以上(1)~(4)是在应用程序Broadcounter中执行的,(5)~(12)是在AMS中执行的。
图4 广播的发送处理过程(5-12)
(5)ActivityManagerService.broadcastIntent
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {public final int broadcastIntent(IApplicationThread caller,Intent intent, String resolvedType, IIntentReceiver resultTo,int resultCode, String resultData, Bundle map,String requiredPermission, boolean serialized, boolean sticky) {synchronized(this) {intent = verifyBroadcastLocked(intent);final ProcessRecord callerApp = getRecordForAppLocked(caller);final int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();int res = broadcastIntentLocked(callerApp, callerApp != null ? callerApp.info.packageName : null,intent, resolvedType, resultTo, resultCode, resultData,map, requiredPermission, serialized, sticky, callingPid, callingUid);Binder.restoreCallingIdentity(origId);return res;}}
}
verifyBroadcastLocked用来校验广播是否合法。在系统的启动过程中PMS可能还未被启动,这种情况下AMS是无法获得静态注册的广播接收者的,应该禁止发送广播给静态注册的广播接收者。
(6)ActivityManagerService.broadcastIntentLocked
这一步是用来查找目标广播接收者的,分段阅读。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNativeimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {public final int broadcastIntentLocked(ProcessRecord callerApp,String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, boolean ordered, boolean sticky, int callingPid, int callingUid){intent = new Intent(intent);...// Add to the sticky list if requestedif (sticky) {...ArrayList<Intent> list = mStickyBroadcasts.get(intent.getAction());if (list == nullptr) {list = new ArrayList<Intent>();mStickyBroadcasts.put(intent.getAction(), list);}int N = list.size();int i;for (i=0;i<N;i++) {// 如果存在if (intent.filterEquals(list.get(i))) {// This sticky already exists, replace itlist.set(i, new Intent(intent));break;}}// 如果不存在if (i>=N) {list.add(new Intent(intent));}} ...
AMS中,所有相同类型的黏性广播都保存在一个列表(mStickyBroadcasts)中。mStickyBroadcasts是个HashMap,关键字为广播类型(intent.getAction())。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
// Figure out who all will receive this broadcast.List receivers = null;List<BroadcastFilter> registerReceivers = null;try {if (intent.getComponent() != null) {// Broadcast is going to one specific receiver class...ActivityInfo ai = AppGlobals.getPackageManager().getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);if (ai != null) {receivers = new ArrayList();ResolveInfo ri = new ResolveInfo();ri.activityInfo = ai;receivers.add(ri);}} else {// Need to resolve the intent to interested receivers...if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {receivers = AppGlobals.getPackageManager().queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS);}registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);}} catch (RemoteException ex) {...}...
如果intent指定了广播接收者的组件名称(intent.getComponent()),就说明广播要发送给特定的广播接收者。通过getReceiverInfo()根据intent组件类型在PMS中找到对应的广播接收者,将广播接收者保存在列表receivers里。
如果intent没有指定广播接收者的组件名称,就说明广播是要发送给所有注册的,并且要接收它的广播接收者的。这些目标广播接收者分为两类:
(1)静态注册的
intent的标志位FLAG_RECEIVER_REGISTERED_ONLY为0,为静态注册的广播接收者,保存在列表receivers。
(2)动态注册的
动态注册的广播接收者保存在AMS类的成员变量mReceiverResolver中,保存在registeredReceivers。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
final boolean replacePending = (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0; int NR = registeredReceivers != null ? registeredReceivers.size() : 0;if (!ordered && NR > 0) {// If we are not serializing this broadcast, then send the registed receivers separately so they don't wait for the components to be launchedBroadcastRecord r = new BroadcastRecord(intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, registeredReceivers, resultTo, resultCode, resultData, map, ordered, sticky, false);...boolean replaced = false;if (replacePending) {for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {...mParallelBroadcasts.set(i, r);replaced = true;break;}}}if (!replaced) {mParallelBroadcasts.add(r);scheduleBroadcastsLocked();}registeredReceivers = null;NR = 0;}
可能会出现这样一种情况:上次接收的广播还没来得及转发给目标广播接收者,又收到了一个同样的广播。这种情况下,如果广播的标志位FLAG_RECEIVER_REPLACE_PENDING为1,那么AMS会使用新的广播来替代旧的广播。
!ordered表示无序广播,NR>0表示存在动态注册的目标广播接收者。
广播转发任务不是立即执行的,而是被添加到AMS的一个无序广播调度队列中等待执行的。(mParallelBroadcasts)
replaced为true表示不需要在AMS的无序广播调度队列里新增广播转发任务;否则,会将BroadcastRecord描述的广播转发任务添加到AMS的无序广播调度队列里,调用scheduleBroadcastsLocked来重新调度队列中的广播转发任务。
截至目前,对于无序广播,AMS已经将广播转发给动态注册的目标广播接收者了。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
// Merge into one list int ir = 0;if (receivers != null) {...int NT = receivers != null ? receivers.size() : 0;int it = 0;ResolveInfo curt = null;BroadcastFilter curr = null;while (it < NT && ir < NR) {if (curt == null) {// 静态注册curt = (ResolveInfo)receivers.get(it);}if (curr == null) {// 动态注册curr = registeredReceivers.get(ir);}if (curr.getPriority() >= curt.priority) {// Insert this broadcast record into the final listreceivers.add(it, curr);ir++;curr = null;it++;NT++; } else {// Skip to the next ResolveInfo in the final listit++;curt = null;}}} while (ir < NR) {if (receivers == null) {receivers = new ArrayList();}receivers.add(registeredReceivers.get(ir));ir++; }
AMS内部用mOrderedBroadcasts来描述一个有序广播调度队列,队列中的每个目标广播接收者都是按照优先级从高到低的顺序来排列,不论是动态注册还是静态注册的。
while循环用来合并动态注册和静态注册的目标广播接收者。合并后的目标广播接收者都保存在列表receivers,它们是按照优先级从高到低的顺序来排列的。
合并之前,保存在registeredReceivers和receivers两个列表中的目标广播接收者都是按照优先级从高到低的顺序排列的。合并后,目标广播接收者仍然按照优先级从高到低的顺序排列在receivers中。
函数执行到这里,无论AMS当前接收到的是一个无序广播,还是有序广播,AMS都会将广播和目标广播接收者封装成一个广播转发任务,并且添加到有序广播调度队列里。只是对于无序广播,当它们真正被转发时,不按照有序广播的方式转发罢了。
截至目前,对于无序广播,静态注册的目标广播接收者保存在receivers了(动态注册的目标广播接收者在registeredReceivers,已经添加到无序广播调度队列里了);对于有序广播,静态注册和动态注册的目标广播接收者都保存在receivers了。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
if ((receivers != null && receivers.size() > 0) || resultTo != null) {BroadcastRecord r = new BroadcastRecord(intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission,receivers, resultTo, resultCode, resultData, map, ordered, sticky, false);...boolean replaced = false;if (replacePending) {for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {...mOrderedBroadcasts.set(i, r);replaced = true;break;}}}if (!replaced) {mOrderedBroadcasts.add(r);scheduleBroadcastsLocked();}return BROADCAST_SUCCESS;}...
}
将intent描述的广播和之前receivers描述的目标广播接收者封装为BroadcastRecord对象r,添加到AMS内部的有序广播调度队列中。
如果replaced为true,说明不需要在AMS的有序广播调度队列中增加新的广播转发任务,就不需要再去调度队列中的广播转发任务。
至此,AMS就找到了广播所描述的目标广播接收者了,分别将它们保存在无序广播调度队列mParallelBroadcasts和有序广播调度队列mOrderedBroadcasts()中。接下来,AMS调用scheduleBroadcastLocked函数将广播转发给目标广播接收者。
总结:
mParallelBroadcasts中存放的是动态注册的无序广播,registeredReceivers。
mOrderedBroadcasts中存放的是静态注册和动态注册的有序广播+静态注册的无序广播,receivers。
(7)ActivityManagerService.scheduleBroadcastLocked
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNativeimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {...private final void schedualBroadcastsLocked() {if (mBroadcastsScheduled) {return;} mHandler.sendEmptyMessage(BROADCAST_INTENT_MSG);mBroadcastsScheduled = true;}
}
mBroadcastsScheduled用来描述AMS是否已经向它所在的线程的消息队列发送了一个类型为BROADCAST_INTENT_MSG的消息。
BROADCAST_INTENT_MSG消息最后是在AMS的成员变量mHandler成员函数handleMessage。
(8)Handler.handle Message
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNativeimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {...final Handler mHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {...case BROADCAST_INTENT_MSG: {...processNextBroadcast(true);} break;...}}}
}
(9)ActivityManagerService.processNextBroadcast
用来将广播转发给目标广播接收者处理,分段阅读。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNativeimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {...private final void processNextBroadcast(boolean fromMsg) {synchronized(this) {BroadcastRecord r;...if (fromMsg) {mBroadcastsScheduled = false;}// First, deliver any non-serialized broadcasts right awaywhile (mParallelBroadcasts.size() > 0) {r = mParallelBroadcasts.remove(0);...final int N = r.receivers.size();...for (int i=0; i<N; i++) {Object target = r.receivers.get(i);...deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);}...}
fromMsg为true,将mBroadcastsScheduled置为false。表示前面发送到AMS运行线程的消息队列中的BROADCAST_INTENT_MSG消息已经被处理了。
如上处理无序广播调度队列。下面处理有序广播调度队列:
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
// if we are waiting for a process to come up to handle the next broadcast, then do nothing at this point.// Just in case, we check that the process we're waiting for still exists.if (mPendingBroadcast != null) {...boolean isDead;synchronized (mPidsSelfLocked) {isDead = mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null;}if (!isDead) {// it's stll alive, so keep waitingreturn;} else {...mPendingBroadcast.state = BroadcastRecord.IDLE;mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;mPendingBroadcast = null;}}
有序广播调度队列mOrderBroadcast的目标广播接收者可能是静态注册的,这些广播接收者可能还没有启动起来。
mPendingBroadcast用来描述一个正在等待静态注册的目标广播接收者的广播的。如果存在这样的广播,会先检查应用程序是否已经启动。
如果应用程序正在启动,AMS会继续等待;如果应用程序没有启动,AMS会向应用程序发送一个广播,应用程序收到AMS发送的广播后,会主动将目标广播接收者启动起来。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
do {if (mOrderedBroadcasts.size() == 0) {...return;}r = mOrderedBroadcasts.get(0);boolean forceReceive = false;...int numReiceivers = (r.receivers != null) ? r.receivers.size() : 0;if (mProcessReady && r.dispatchTime > 0) {long now = SystemClock.uptimeMillis();if ((numReceivers > 0) && (now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {...// forcibly finish this broadcastbroadcastTimeoutLocked(false);forceReceive = true;r.state = BroadcastRecord.IDLE;}}// 检查r描述的广播转发任务是否正在处理中if (r.state != BroadcastRecord.IDLE) {...return;}// 检查r描述的广播转发任务是否已经完成或已经被强制结束if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) {//No more receivers for this broadcast! Send the final result if requested......cancelBroadcastTimeoutLocked();...// ... and on to the next ......mOrderedBroadcasts.remove(0);r = null;...continue;}} while (r == null);
先检查目标广播接收者是否在规定的时间内处理完AMS给它发送的一个有序广播。如果超时,调用broadcastTimeoutLocked来强制结束这个广播任务。
循环跳出后,下一个需要处理的广播转发任务就保存在r中了。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
// Get the next receiver...int recIdx = r.nextReceiver++;// Keep track of when this receiver started, and make sure there is a timeout message pending to kill it if need be.r.receiverTime = Systemclock.uptimeMillis();if (recIdx == 0) {r.dispatchTime = r.receiverTime;...}// 检查AMS是否已经向它所运行的线程的消息队列发送了类型为BROADCAST_TIMEOUT_MSG的消息if (!mPendingBroadcastTimeoutMessage) {long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;setBroadcastTimeoutLocked(timeoutTime);} Object nextReceiver = r.receivers.get(recIdx);if (nextReceiver instanceof BroadcastFilter) {// Simple case: this is a registered receiver who gets a direct call.BroadcastFilter filter = (BroadcastFilter)nextReceiver;....deliverToRegisteredReceiverLocked(r, filter, r.ordered);// 检查r所描述的广播转发任务是否是用来转发无序广播的或广播已经处理完成if (r.receiver == null || !r.ordered) {// The receiver has already finished, so schedule to process the next one...// 因为是无序广播或已经处理完的广播,所以AMS不需要等待它的前一个广播处理完成就可以将该广播发送给它的下一个目标r.state = BroadcastRecord.IDLE;scheduleBroadcastLocked();} return;}
由(6)可知,如果下一个目标广播接收者nextReceiver的类型为BroadFilter,那么就说明它是一个动态注册的广播接收者。那么就可以直接调用deliverToRegisteredReceiverLocked发送一个广播,因为动态注册的广播接收者一定是已经启动的。
如果下一个目标广播接收者nextReceiver的类型不是BroadFilter,就说明这是一个静态注册的广播接收者(ResolveInfo)。这种情况较为复杂,因为静态注册的广播接收者可能还没有启动。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
// Hard case: need to instantiate the receiver, possibly starting its application process to host it.ResolveInfo info = (ResolveInfo)nextReceiver;...String targetProcess = info.activityInfo.processName;...// Is this receiver's application already running?ProcessRecord app = getProcessRecordLocked(targetProcess, info.activityInfo.applicationInfo.uid);if (app != null && app.thread != null) {try { processCurBoardcastLocked(r, app);return;} catch (RemoteException e) {...}...}// Not running -- get it started, to be executed when the app come up.if ((r.curApp = startProcessLocked(...)) == null) {// this recipient(接收者) is unavaiable. Finish it if necessary, and mark the broad cast record as ready fot the next....scheduleBroadcastLocked();r.state = BroadcastRecord.IDLE;return;} mPendingBroadcast = r;mPendingBroadcastRecnIndex = recIdx;}}...
}
如果应用程序已经启动,调用processCurBoardcastLocked将广播发送给它处理;启动失败,调用scheduleBroadcastLocked来结束对广播r的转发任务的处理。将r和recIdx保存在mPendingBroadcast和mPendingBroadcastRecnIndex中,表示AMS正在等待r所描述的广播转发任务的下一个目标广播接收者所在的应用程序进程启动起来。
假设r所描述的广播转发任务的下一个目标接收者是一个动态注册的广播接收者,或是一个静态注册的已经启动的广播接收者,下一步会调用deliverToRegisteredReceiverLocked来转发广播。
(10)AcitvityManagerService.deliverToRegisteredReceiverLocked
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNativeimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {...private final void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered) {boolean skip = false;// 发送者权限if (filter.requiredPermission != null) {int perm = checkComponentPermission(filter.requiredPermission, r.callingPid, r.callingUid, -1);if (perm != PackageManager.PERMISSION_GRANTED) {...skip = true;}}// 接收者权限if (r.requiredPermission != null) {int perm = checkComponentPermission(r.requiredPermission, filter.receiverList.pid, filter.receiverList.uid, -1);if (perm != PackageManager.PERMISSION_GRANTED) {...skip = true;}} if (!skip) {...try {performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky);} catch (RemoteException e) {...}}}
}
需要检查广播发送者和接收者的权限。检查是双向的,即检查发送者是否有权限向接收者发送广播,检查接收者是否有权限接收来自发送者的广播。
(11)AcitvityManagerService.performReceiveLocked
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNativeimplements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {...static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent,int resultCode, String data, Bundle extras, boolean ordered, boolean sticky) throws RemoteException {// Send the intent to the receiver asynchronously using one-way binder callsif (app != null && app.thread != null) {// if we have an app thread, do the call through that so it is correctly ordered with other one-way callsapp.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky);} else {receiver.performReceive(intent, resultCode, data, extras, ordered, sticky);} }
}
app描述目标广播接收者所运行的应用程序进程;receiver实现了IIntentReceiver接口的Binder代理对象,描述目标广播接收者;intent用来描述要发送给目标广播接收者的广播。
如果目标广播接收者需要通过它所运行的应用程序进程来接收一个广播,那么会调用运行在应用程序进程中的ApplicationThread对象的Binder代理对象的成员函数scheduleRegisteredReceiver来向它发送这个广播;否则,直接调用IntentReceiver对象的Binder代理对象的成员函数perfromReceive来向它发送这个广播。
假设app.thread != null,app描述的应用进程即为Broadcounter所运行的进程,app.thread为Broadcounter进程的一个ApplicationThread对象的Binder代理对象,即ApplicationThreadProxy对象。
(12)ApplicationThreadProxy.scheduleRegisteredReceiver
frameworks/base/core/java/android/app/ApplicationThreadNative.java
class ApplicationThreadProxy implements IApplicationThread {...public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode,String dataStr, Bundle extras, boolean ordered, boolean sticky) throws RemoteException {Parcel data = Parcel.obtain();data.writeInterfaceToken(IApplicationThread.descriptor);data.writeStrongBinder(receiver.asBinder());intent.writeToParcel(data, 0);data.writeInt(resultCode);data.writeString(dataStr);data.writeBundle(extras);data.writeInt(ordered?1:0);data.writeInt(sticky?1:0);mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);data.recycle();}
}
IBinder.FLAG_ONEWAY表示进程间通信是异步的。
以上8步是在AMS进程中执行的,下面13-17步是在应用程序Broadcounter进程中执行的,用来处理AMS发出的SCHEDULE_REGISTERED_RECEIVER_TRANSACTION的进程间通信请求。
图5 广播的发送处理过程(13-17)
(13)ApplicationThread.scheduleRegisteredReceiver
frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread {...private final class ApplicationThread extends ApplicationThreadNative {...public void schedualRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCodeString dataStr, Bundle extras, boolean ordered, boolean sticky) throws RemoteException {receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);}}
}
(14)InnerReceiver.performReceive
frameworks/base/core/java/android/app/LoadedApk.java
final class LoadedApk {...static final class ReceiverDispatcher {final static class InnerReceiver extends IIntentReceiver.Stub {final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;...public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky) {LoadedApk.ReceiverDispacher rd = mDispatcher.get();...if (rd != null) {rd.performReceive(intent, resultCode, data, extras, ordered, sticky);}}}}
}
mDispatcher是ReceiverDispacher的弱引用,rd.performReceive实际上是调用ReceiverDispatcher的performReceive函数来接收intent描述的广播。
(15)ReceiverDispatcher.performReceive
frameworks/base/core/java/android/app/LoadedApk.java
final class LoadedApk {...static final class ReceiverDispatcher {...final Handler mActivityThread;...public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky) {...Args args = new Args();args.mCurIntent = intent;args.mCurCode = resultCode;args.mCurData = data;args.mCurMap = extras;args.mCurOrdered = ordered;args.mCurSticky = sticky;if (!mActivityThread.post(args)) {...}}...}
}
mActivityThread Handler对象指向ActivityThread类的成员变量mH,用来向Broadcounter的主线程的消息队列发送消息。将intent封装成一个Args对象,发送到Broadcounter的主线程的消息队列中。这个消息是在Args类的run函数中处理的。
(16)Args.run
frameworks/base/core/java/android/app/LoadedApk.java
final class LoadedApk {...static final class ReceiverDispatcher {...final BroadcastReceiver mReceiver;final boolean mCurOrderred;...public void run() {BroadcastReceiver receiver = mReceiver;...IActivityManager mgr = ActivityManagerNative.getDefault();Intent intent = mCurIntent;...try {receiver.onReceive(mContext, intent);} catch (Exception e) {...}if (mRegistered && mCurOrdered) {try {mgr.finishReceiver(mIIntentReceiver, receiver.getResultCode(), receiver.getResultData(), receiver.getResultExtras(false), receiver.getAbortBroadcast());} catch (RemoteException e) {...}}}}
}
mRegistered用来描述mReceiver指向的广播接收者是否已经注册到AMS。mCurOrdered表示是否是一个有序广播。
如果广播接收者是否已经注册到AMS且是一个有序广播,需要调用AMS代理对象mgr的成员函数finishReceiver来通知AMS,它前面转发出来的有序广播已经处理完了。这时,AMS可以继续将这个有序广播转发给下一个目标广播接收者处理。
(17)BroadcastReceiver.onReceive
/package/experimental/Broadcounter/xxx/Broadcounter.java
public class Broadcounter extends Activity implements OnClickListener {...private BroadcastReceiver counterActionReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {int counter = intent.getIntExtra(CounterService.COUNTER_VALUE, 0);String text = String.valueof(counter);counterText.setText(text);}}
}
intent用来描述广播。context用来描述将广播接收者注册到AMS中的Activity组件或Service组件。
3 Android应用程序的线程消息循环模型(ActivityThread,HandlerThread,AsyncThread)
对于不定期的后台任务来说,有两种处理方式。
(1)每当条件满足,就创建一个子线程来执行一个不定期的后台任务;当任务执行完毕后,新创建的子线程随之退出。
(2)创建一个具有消息循环的子线程,每当条件满足时,就将一个不定期的后台任务封装成一个消息发送到这个子线程的消息队列中去执行;当条件不满足时,子线程因为消息队列为空而进入睡眠等待状态。Android采用第2种。
Android应用程序线程的三种消息循环模型。
(1)应用程序主线程消息循环模型
(2)与界面无关的应用程序子线程消息循环模型
(3)与界面相关的应用程序子线程消息循环模型
3.1 应用程序主线程消息循环模型ActivityThread
AMS在启动一个应用程序组件时,如果发现这个应用程序组件需要在一个新的应用程序进程中进行,就会调用Process类的静态成员函数start来请求Zygote进程创建一个新的应用程序进程。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {...private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) {... try {...int pid = Process.start("android.app.ActivityThread", mSimpleProcessManagement ? app.processName : null,uid, uid, gids, debugFlags, null);} catch (RuntimeException e) {...}}
}
每一个新创建的应用程序进程(主线程)都是以ActivityThread类的静态成员函数main来作为入口函数的。
frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread {...public static final void main(String[] args) {...Looper.prepareMainLooper();...Looper.loop();}
}
prepareMainLooper函数在当前应用程序主线程中创建一个消息循环,loop函数使得当前应用程序主线程进入到前面创建的消息循环中。
prepareMainLooper首先创建一个Looper对象,描述一个应用程序主线程的消息循环;然后在Looper对象上创建一个MessageQueue对象,描述一个应用程序主线程的消息队列。prepareMainLooper只能在应用程序主线程中调用,且只能被调用一次,否则系统抛出运行时异常。
为什么Looper类要单独为应用程序主线程提供一个创建Looper对象的函数呢?
Looper对象除了会保存在一个线程局部变量中之外,还会单独保存在Looper类的静态成员变量mMainLooper中。这样,应用程序子线程就可以通过这个mMainLooper对象向主线程的消息队列发送与UI相关的消息了。
3.2 与界面无关的应用程序子线程消息循环模型HandlerThread
通过一个例子来说明如何使用一个Thread子类来创建一个Android应用程序子线程:
public class SubThread extends Thread {public SubThread(String name) {super(name);}public void run() {...}
}SubThread subThread = new SubThread("Sub Thread");
subThread.start();
创建SubThread类实例,调用start函数来启动一个子线程:
SubThread subThread = new SubThread("Sub Thread");
subThread.start();
为了创建一个具有消息循环的应用程序子线程,可以通过framework层提供的HandlerThread类来实现:
frameworks/base/core/java/android/os/HandlerThread.java
public class HandlerThread extends Thread {...private Looper mLooper;public HandlerThread(String name) {super(name);...}public void run() {...Looper.prepare();synchronized (this) {mLooper = Looper.myLooper();}Looper.loop();...}public Looper getLooper() {return mLooper;}public boolean quit() {Looper looper = getLooper();if (looper != null) {looper.quit();return true;}return false; }
}
Looper类的prepare函数用作子线程创建一个消息循环,loop函数使得当前线程进入到前面所创建的消息循环中。
来说明下如何使用HandlerThread类创建一个Android应用子线程:
(1)创建HandlerThread类实例,调用start函数来启动一个子线程:
HandlerThread handlerThread = new HandlerThread("Handler Thread");
handlerThread.start();
(2)定义一个实现了Runnable接口的类,用来描述任务:
public class ThreadTask implements Runnable {public ThreadTask() {}public void run() {...}
}
(3)创建一个ThreadTask类实例:
ThreadTask threadTask = new ThreadTask();
(4)将ThreadTask类实例封装成一个消息发送到HandlerThread子线程的消息队列中:
Handler handler = new Handler(handlerThread.getLooper());
handler.post(threadTask);
当这个消息被处理时,HandlerThread子线程会调用ThreadTask的run函数。
(5)需要结束子线程时:
handlerThread.quit();
frameworks/base/core/java/android/os/Looper.java
public class Looper {....final MessageQueue mQueue;public void quit() {Message msg = Message.obtain();// a quit messagemQueue.enqueueMessage(msg, 0);}
};
如果我们向一个线程的消息队列发送的target为null的Message对象,那么这个线程会退出消息循环。
3.3 与界面相关的应用程序子线程消息循环模型AsyncThread
异步任务类AsyncTask,子线程虽然没有自己的消息循环,但是它可以利用主线程的消息循环来执行与UI相关的操作。
CounterService,当调用startCounter函数时,它会在一个子线程中执行异步任务。这个异步任务每隔1秒就会将它内部的一个计数值增加1,且将计数值更新到UI上。
package/xxx/CounterService.java
public class CounterService extends Service implements ICounterService {...private ICounterCallback counterCallback = null;public void startCounter(int initVal, ICounterCallback callback) {counterCallback = callback;AsyncTask<Integer, Integer, Integer> task = new AsyncTask<Integer, Integer, Integer>() {@Override //子线程protected Integer doInBackground(Integer... vals) {Integer initCounter = vals[0];stop = false;while(!stop) {publishProgress(initCounter);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}initCounter++;}return initCounter;}@Override //主线程protected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);int val = values[0];counterCallback.count(val);}@Override //主线程protected void onPostExecute(Integer val) {counterCallback.count(val);}};task.execute(initVal);}
}
callback是一个计数器回调接口,调用它的count函数可以将计数值更新到UI上。
异步任务task是在doInBackground中执行的,运行在子线程中。每隔1s会将计数值加一,调用publishProgress将计数值分发给onProgressUpdate来处理,onProgressUpdate会调用回调将计数值显示在UI上。doInBackground的返回值会分发给onPostExecute来处理,onPostExecute会调用回调将计数值显示在UI上。
onProgressUpdate和onPostExecute执行了与UI有关的操作,推断出它们是在应用程序主线程中运行的。
可以看出,一个异步任务虽然是在子线程中执行的,但是它可以执行与UI有关的操作,来分析下:
先看下异步任务类AsyncTask类的定义:
frameworks/base/core/java/android/os/AsyncTask.java
public abstract class AsyncTask<Params, Progress, Result> {...private static final BlockingQueue<Runnable> sWorkQueue = new LinkedBlockingQueue<Runnable>(10);private static final ThreadFactory sThreadFactory = new ThreadFactory() {private final AtomicInteger mCount = new AtomicInteger(1);public Thread newThread(Runnable r) {return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());}};private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);private static final int MESSAGE_POST_RESULT = 0x1;private static final int MESSAGE_POST_PROGRESS = 0x2;private static final int MESSAGE_POST_CANCEL = 0x3;private static final InternalHandler sHandler = new InternalHandler();private final WorkerRunnable<Params, Result> mWorker;private final FutureTask<Result> mFuture;
}
类型参数Params、Progress和Result,分别描述异步任务的输入数据、过程数据和结果数据。
sWorkQueue表示工作任务队列,队列为空时阻塞,队列满时也阻塞。
sThreadFactory表示一个类型为ThreadFactory的线程创建工厂,创建的线程用来执行sWorkQueue队列里的任务。
sExecutor表示一个类型为ThreadPoolExecutor的线程池,保存在线程池的线程是sThreadFactory创建的。
ThreadPoolExcutor(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
corePoolSize:核心线程数量
maximumPoolSize:最大线程数量
当线程池中的线程数量大于核心线程数量时,里面的空闲线程会设置一个存活时间,由keepAliveTime来描述,时间单位由unit来描述。
workQueue:工作任务队列
threadFactory:线程创建工厂
由于sWorkQueue、sThreadFactory和sExecutor都是静态成员变量,因此,在一个应用程序进程中,所有使用异步任务类AsyncTask来描述的异步任务都是在同一个线程池中执行的。
sHandler指向一个Handler对象,静态变量是在程序第一次使用时创建的,假设应用程序第一次使用异步任务类AsyncTask时是运行在主线程的,那么sHandler所指向的Handler就是在应用程序的主线程中创建的,这意味着它可以用来向应用程序主线程的消息队列发送消息。
mWorker和mFuture用来描述一个工作任务。
来看下InternalHandler:
frameworks/base/core/java/android/os/AsyncTask.java
public abstract class AsyncTask<Params, Progress, Result> {...private static class InternalHandler extends Handler {@Overridepublic void handleMessage(Message msg) {AsyncTaskResult result = (AsyncTaskResult) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:result.mTask.finish(result.mData[0]);break;case MESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate(result.mData);break;case MESSAGE_POST_CANCEL:result.mTask.onCanceled();break;}}} private static class AsyncTaskResult<Data> {final AsyncTask mTask;final Data[] mData;AsyncTaskResult(AsyncTask task, Data... data) {mTask = task;mData = data;}}private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {Params[] mParams;}
}
MESSAGE_POST_RESULT,MESSAGE_POST_PROGRESS和MESSAGE_POST_CANCEL都是由异步任务的子线程发送到主线程的消息队列的。
mTask表示一个宿主异步任务。mParams数组用来保存一个异步任务的输入数据。
下面,来分析一个异步任务的创建过程:
frameworks/base/core/java/android/os/AsyncTask.java
public abstract class AsyncTask<Params, Progress, Result> {...public AsyncTask() {mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {...return doInBackground(mParams);}};mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected void done() {Message message;Result result = null;try {result = get();} catch (InterruptedException e) {android.util.Log.w(LOG_TAG, e);} catch (ExecutionException e) {throw new RuntimeException();} catch (CancellationException e) {message = sHandler.obtainMessage(MESSAGE_POST_CANCEL, new AsyncTaskResult<Result>(AsyncTask.this, null));message.sendToTarget();return;} catch (Throwable t) {throw new RuntimeException();}message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(AsyncTask.this, result));message.sendToTarget();}};}
}
一个异步任务在创建完成之后,就会在内部获得一个mWorker和mFuture,它们共同描述了一个即将执行的工作任务。
当工作任务执行完成后,done被调用。done函数会封装一个类型为MESSAGE_POST_RESULT的消息,通过sHandler对象将这个消息发送到应用程序主线程的消息队列中。mFuture.get()用来描述一个工作任务的执行结果数据,返回值对应于AsyncTask类的函数doInBackground的返回值。
一个异步任务在执行过程中是可以被取消的。这种情况下,在获取结果数据时,会得到一个类型为CancellationException的异常,done函数会封装一个类型为MESSAGE_POST_CANCEL的消息,通过sHandler对象将这个消息发送到应用程序主线程的消息队列中。
下面继续分析这个工作任务的执行过程:
public abstract class AsyncTask<Params, Progress, Result> {...public final AsyncTask<Params, Progress, Result> execute(Params... params) {...mWorker.mParams = params;sExecutor.execute(mFuture);return this;}protected abstract Result doInBackground(Params... params);
}
mFuture描述的工作任务,加入到线程池中去执行。执行过程中,会调用内部的一个Callable对象的call函数,这个Callable对象就是mWorker对象,进而调用doInBackground函数。doInBackground是一个抽象方法,AsyncTask子类通过重写这个方法就可以执行一个自定义的异步任务。
1 MESSAGE_POST_PROGRESS
一个异步任务在执行的过程中,如果需要执行与界面相关的操作,那么它就需要调用异步任务类AsyncTask的函数publishProgress,以便可以向应用程序主线程的消息队列发送一个消息。
public abstract class AsyncTask<Params, Progress, Result> {...protected final void publishProgress(Progress... values) {sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget();}protected void onProgressUpdate(Progress... values) {}
}
sHandler发送的消息最终是由成员函数handleMessage来处理的。MESSAGE_POST_PROGRESS消息会由onProgressUpdate函数来处理。AsyncTask子类通过重写这个方法可以在一个异步任务的执行过程中执行一系列与界面相关(主线程)的操作。
2 MESSAGE_POST_RESULT
从handleMessage可以看出,类型为MESSAGE_POST_RESULT的消息最终是在AsyncTask的finish函数中处理的。
public abstract class AsyncTask<Params, Progress, Result> {...private void finish(Result result) {if (isCancelled()) result = null;onPostExecute(result);...}protected void onPostExecute(Result result) {}
}
AsyncTask子类通过重写这个方法可以在一个异步任务的执行完成时执行与界面相关(主线程)的操作。
3 MESSAGE_POST_CANCEL
从handleMessage可以看出,类型为MESSAGE_POST_CANCEL的消息最终是在AsyncTask的onCancelled函数中处理的。
public abstract class AsyncTask<Params, Progress, Result> {...protected void onCancelled() {}
}
AsyncTask子类通过重写这个方法可以在一个异步任务被取消时执行与界面相关(主线程)的操作。