Android广播注册机制剖析【android广播系列一】

广播是android四大组件之一,所以广播的重要性也是显而易见的,最近需要做个功能,需要对广播的机制深入了解,所以我就整理下思路。平时我们写代码的时候,广播只是用来通知机制的,不是用来通信机制,通信机制还是要用binder机制来实现。但是现在市场上的第三方app大部分都是滥用广播,用广播来监听一些事件来实现自启动或者后台启动。这就误解了谷歌的意思。本来很好的组件,被大家滥用,导致用户老是感觉手机的程序控制不住,老是后台偷偷启动。小白用户甚至更不理解了。好了现在言归正传。 android广播按发送方式分为三种:

广播按照注册方式分为两种:

静态广播

动态广播

摘录老罗文章“广播机制是一种基于消息发布和订阅的事件驱动模型,即广播发送者负责发布消息,而广播接收者需要先订阅消息,然后才能接收到消息。在广播机制中,广播发送者事先不需要知道广播接收者的存在的,这样就能大大降低广播发送者和广播接收者之间的耦合度,进而提高系统的可扩展性和可维护性。” 广播的正真机制就两种情况,注册广播的机制,和接收广播的机制,我们先来谈谈注册广播的流程。 注册广播的流程:分为动态注册和静态注册两种; (1)先来说说动态注册广播 Step1:说明: ReceiverDispatcher是frameworks/base/core/java/android/app/LoadedApk.java的内部类,这个类是保存广播接收者的组件(Activity或者Service),负责将这个被注册的广播接收者和注册它的组件关联在一起。

{ IIntentReceiver.Stub {. . . . . .. . . . . .}// 请注意这个域!它就是传到外面的rd。final IIntentReceiver.Stub mIIntentReceiver;final BroadcastReceiver mReceiver;final Context mContext;final Handler mActivityThread;final Instrumentation mInstrumentation;final boolean mRegistered;final IntentReceiverLeaked mLocation;RuntimeException mUnregisterLocation;boolean mForgotten;. . . . . .

Step2:好了先说说需要了解的知识。registerReceiver(),是通过context来注册的,调用过程最后调用到ContextImpl这个对象中,

@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {return registerReceiver(receiver, filter, null, null);}@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) {return registerReceiverInternal(receiver, filter, broadcastPermission, scheduler, getOuterContext());}

Step3:我们接着来看看registerReceiverInternal()这个方法:

private Intent registerReceiverInternal(BroadcastReceiverreceiver, IntentFilter filter, StringbroadcastPermission, Handler scheduler, Context context) {IIntentReceiver rd = null;if (receiver != null) {if (mPackageInfo != null && context != null) {if (scheduler == null) {scheduler = mMainThread.getHandler();}// 查找和context对应的“子哈希表”里的ReceiverDispatcher,//如果找不到,就重新new一个rd = mPackageInfo.getReceiverDispatcher(receiver, context, scheduler,mMainThread.getInstrumentation(), true);} else {if (scheduler == null) {scheduler = mMainThread.getHandler();}rd = new LoadedApk.ReceiverDispatcher(…, …);}. . . . . .}try {return ActivityManagerNative.getDefault().registerReceiver(mMainThread.getApplicationThread(), mBasePackageName,rd, filter, broadcastPermission);} catch (RemoteException e) {return null;}}

Step4:大家注意那个rd对象(IIntentReceiver rd),首先调用成员变量mPackageInfo的成员函数(是LoadedApk的一个对象)getReceiverDispatcher()将广播接收者receiver封装成一个实现了IIntentReceiver接口的Binder的本地对象rd,最后将这个对象发送给AcitivityManagerService。 接着来看看getReceiverDispatcher()这个方法:

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,Context context, Handler handler,Instrumentation instrumentation, boolean registered) {synchronized (mReceivers) {LoadedApk.ReceiverDispatcher rd = null;//注册过广播接收者与注册它的组件关联在一起ArrayMap;//已经注册过了if (registered) {map = mReceivers.get(context);) {rd get(r);}}) {rd = new ReceiverDispatcher(r, context, handler,instrumentation, registered);if (registered) {) {ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();mReceivers.put(context, map);}map.put(r, rd);}} else {rd.validate(context, handler);}rd.mForgotten = false;//来获得一个实现了IIntentReceiver接口的Binder的本地对象return rd.getIIntentReceiver();}}IIntentReceiver getIIntentReceiver() {return mIIntentReceiver;}读书破万卷,下笔如有神。

Android广播注册机制剖析【android广播系列一】

相关文章:

你感兴趣的文章:

标签云: