Android广播机制实现源码浅析(二)
来源:互联网 发布:java base64编解码 编辑:程序博客网 时间:2024/04/27 15:00
紧接着上篇的分析,我们现在来分析一下处理广播的代码流程,也就是在方法queue.scheduleBroadcastsLocked();之后的操作
这些方法在BroadcastQueue.java中。在这里能看到我们常说的广播超时,以及我们重写onReceive什么时候执行。
可以看到这里在分发广播时直接post一个消息到队列中,不影响后面的此过程的后续操作,这说明发送和处理广播是一个异步操作,后面才是真正的处理过程。
这里的receiver就是在广播注册过程中关联上的,它的实现是Loadedapk. ReceiverDispatcher. InnerReceiver,这个在动态注册广播时ContextImpl中的registerReceiverInternal方法中有体现,继续往下:
这里mActivityThread成员变量的类型为Handler,它是前面动态注册广播接收器时,从ActivityThread取得的应用主线程的Handler,并把消息post到消息队列中去,因此,ReceiverDispatcher不等这个广播被应用处理就返回了,这里也体现了广播的发送和处理是异步进行的。 最终执行的是Args里面的run方法,在这里执行了注册时保存的BroadcastReceiver实例的onReceive方法。这样就完成了一次广播处理过程。
说到这里我们分析了一个动态注册广播接收器处理非有序广播的过程,也留下了两个疑问,一个是静态广播以及有序广播的处理过程,还有一个就是前面提到的广播超时问题没有说明,下篇将对这两个问题进行继续分析。
这些方法在BroadcastQueue.java中。在这里能看到我们常说的广播超时,以及我们重写onReceive什么时候执行。
public void scheduleBroadcastsLocked() { if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts [" + mQueueName + "]: current=" + mBroadcastsScheduled); if (mBroadcastsScheduled) { return; } mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); mBroadcastsScheduled = true;}final Handler mHandler = new Handler() { //public Handler() { // if (localLOGV) Slog.v(TAG, "Handler started!"); //} public void handleMessage(Message msg) { switch (msg.what) { case BROADCAST_INTENT_MSG: { if (DEBUG_BROADCAST) Slog.v( TAG, "Received BROADCAST_INTENT_MSG"); processNextBroadcast(true); } break; case BROADCAST_TIMEOUT_MSG: { synchronized (mService) { broadcastTimeoutLocked(true); } } break; } }};
可以看到这里在分发广播时直接post一个消息到队列中,不影响后面的此过程的后续操作,这说明发送和处理广播是一个异步操作,后面才是真正的处理过程。
final void processNextBroadcast(boolean fromMsg) {……// First, deliver any non-serialized broadcasts right away. while (mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); r.dispatchTime = SystemClock.uptimeMillis(); r.dispatchClockTime = System.currentTimeMillis(); final int N = r.receivers.size(); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast [" + mQueueName + "] " + r); for (int i=0; i<N; i++) { Object target = r.receivers.get(i); if (DEBUG_BROADCAST) Slog.v(TAG, "Delivering non-ordered on [" + mQueueName + "] to registered " + target + ": " + r); deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); } addBroadcastToHistoryLocked(r); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast [" + mQueueName + "] " + r); }……}这里的先处理的是mParallelBroadcasts中的接收器,前文的分析中得知这个里面的接收器全部都是无序广播接收器中动态注册的,而静态注册的以及有序广播的都是在mOrderedBroadcasts中,本文先对无序动态的流程进行说明。<pre name="code" class="html">private final void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered) {…… try { if (DEBUG_BROADCAST_LIGHT) { int seq = r.intent.getIntExtra("seq", -1); Slog.i(TAG, "Delivering to " + filter + " (seq=" + seq + "): " + r); } performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky, r.userId); if (ordered) { r.state = BroadcastRecord.CALL_DONE_RECEIVE; } } catch (RemoteException e) { Slog.w(TAG, "Failure sending broadcast " + r.intent, e); if (ordered) { r.receiver = null; r.curFilter = null; filter.receiverList.curBroadcast = null; if (filter.receiverList.app != null) { filter.receiverList.app.curReceiver = null; } } }}private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { // Send the intent to the receiver asynchronously using one-way binder calls. if (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 calls. app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); }}这里的app.thread就是发送广播应用的ApplicationThreadProxy,这里用到了跨进程通信的知识,简要说一下,所有的应用进程在创建时就新建了一个activitythread和一个appliacationthread,前者用于处理主线程的用户交互操作和界面刷新操作。后者主要用户和system service进行跨进程的调用。ApplicationThread是ActivityThread的一个内部类,所以接下来看文件ActivityThread.java中的<pre name="code" class="html">public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser);}
这里的receiver就是在广播注册过程中关联上的,它的实现是Loadedapk. ReceiverDispatcher. InnerReceiver,这个在动态注册广播时ContextImpl中的registerReceiverInternal方法中有体现,继续往下:
static final class ReceiverDispatcher {final static class InnerReceiver extends IIntentReceiver.Stub {public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { ……If (rd != null) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } ……..}} public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { if (ActivityThread.DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq + " to " + mReceiver); } Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser); if (!mActivityThread.post(args)) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManagerNative.getDefault(); if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing sync broadcast to " + mReceiver); args.sendFinished(mgr); } } }final class Args extends BroadcastReceiver.PendingResult implements Runnable {public void run() { ………try { ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); setExtrasClassLoader(cl); receiver.setPendingResult(this); receiver.onReceive(mContext, intent); } catch (Exception e) { if (mRegistered && ordered) { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing failed broadcast to " + mReceiver); sendFinished(mgr); } if (mInstrumentation == null || !mInstrumentation.onException(mReceiver, e)) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); throw new RuntimeException( "Error receiving broadcast " + intent + " in " + mReceiver, e); } } if (receiver.getPendingResult() != null) { finish(); }……………}}}
这里mActivityThread成员变量的类型为Handler,它是前面动态注册广播接收器时,从ActivityThread取得的应用主线程的Handler,并把消息post到消息队列中去,因此,ReceiverDispatcher不等这个广播被应用处理就返回了,这里也体现了广播的发送和处理是异步进行的。 最终执行的是Args里面的run方法,在这里执行了注册时保存的BroadcastReceiver实例的onReceive方法。这样就完成了一次广播处理过程。
说到这里我们分析了一个动态注册广播接收器处理非有序广播的过程,也留下了两个疑问,一个是静态广播以及有序广播的处理过程,还有一个就是前面提到的广播超时问题没有说明,下篇将对这两个问题进行继续分析。
0 0
- Android广播机制实现源码浅析(二)
- Android广播机制实现源码浅析(二)
- Android广播机制实现源码浅析(一)
- Android广播机制实现源码浅析(三)
- Android广播机制实现源码浅析(一)
- Android广播机制实现源码浅析(三)
- android 广播机制二
- Android 广播机制(二
- Android广播机制二
- Android笔记(二十四)广播机制
- Android 广播内部机制详解(二)
- Android中的广播机制(二)----- 发送广播
- 广播机制(二)
- android 消息机制浅析(二)
- Android消息处理机制源码分析(二):本地实现
- Android深入浅出系列之广播机制—Android中的广播机制(二)
- android广播机制的实现
- Android 中广播实现机制
- div+css左右结构 一边固定另一边自适应技巧
- java转换流,io流规律
- 西班牙惨败,球王贝利的预言已实现一半
- 第二十八天 月出惊山鸟 —Spring的AOP
- oracle cluster 物理配置要求及限制
- Android广播机制实现源码浅析(二)
- 《统计学基本概念和方法》读书笔记+读后感(1)
- lubuntu调整ls字体颜色
- 20130221-STM32关于各种头文件No such file or directory的详细解决方法
- notepad++ 替换
- [Linux内存]内核内存debug相关
- [Java 15 反射机制 ] Class.forName 得到 Class 对象
- Spring自动装配
- 用C语言实现函数void * memmove(void *dest, const void *src, size_t n)