Android系统广播(3)–客户端广播处理流程
接第二部分由AMS回调客户端ActivityThread方法处理新广播,这里回调两个方法分别处理静态注册接收器和动态注册接收器。如下图流程也由此开始:
一、处理动态广播接收器
1.动态广播由AMS回调ApplicationThread.scheduleRegisteredReceiver()函数
更新下当前进程状态。
回调传入参数IIntentReceiver.performReceive()函数,这个传入对象是广播接收器动态注册时传入AMS端供AMS回调的Binder对象,真正实现在LoadedApk.ReceiverDispatcher.InnerReceiver中。
2.在LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive()中处理
首先获取对象LoadedApk.ReceiverDispatcher,这个对象对应一个注册的BroadcastReceiver并由其分发广播给对应接收器。
判断LoadedApk.ReceiverDispatcher对象是否为空,不为空直接回调其performReceive()。如果是空代表在收到广播前该接收器已经反注册,此时需要通知AMS该广播处理结束。
3.在LoadedApk.ReceiverDispatcher.performReceive()中处理
构造对象Args继承PendingResult实现Runnable,覆写方法run()实现广播分发逻辑。PendingResult代表一个广播处理结果,在接收器onReceive()中如果需要执行耗时操作,可以获取这个对象操作执行完成调用其finish()通知AMS广播处理结束。
调用Handler发布这个Args对象等待执行。这里可以指定不同线程的Handler默认是主线程中执行。
4.在Args.run()中执行
为intent设置对应类加载器,为receiver设置pendingResult接着回调其onReseive()方法给开发者。
获取receiver对应的pendingResult,当调用BroadcastReceiver的goAsync时,会将pendingResult置为null。这里不为null时代表没有调用,直接回调finish()通知AMS。
5.广播处理结束调用finish()函数通知AMS
首先判断该广播发生给的接收器类型
如果是静态广播接收器,等待其对应进程是否存在未完成的work。接着调用sendFinished()函数通知AMS。
如果是动态广播接收器,则其对应广播类型必须是有序并且目前还未被反注册。接着调用sendFinished()函数通知AMS。
最后在sendFinished()函数中根据类型调用不同接口通知AMS广播已经处理完毕。
这里体现了非动态无序广播必须在广播处理完毕之后通知AMS这样才会进行下一次广播的发送操作。
二、处理静态广播接收器
1.静态广播有AMS回调ApplicationThread.scheduleReceiver()处理
首先更新进程状态
新建对象ReceiverData封装传入参数,其负类也是PengdingResult,其中type字段是TYPE_COMPONENT。这个字段在广播处理结束时根据其值调用AMS制定接口。
handler发送异步消息携带数据
2.异步任务中调用handleReceiver()接着处理
首先获取静态接收器的类名,获取其对应的LoadedApk通过这个对象获取接收器对应的ClassLoader。
使用对应的ClassLoder反射获取该静态广播接收器的实例,获取这个静态接收器对象的Application对象及进而获取其对应的Context对象。
最后将ReceiverData设置进静态广播接收器,然后就可以回调对应的onReceive()方法,执行业务方自己的接受广播后逻辑。
3.广播处理结束调用finish()函数通知AMS与上述处理动态广播步骤5一致。