1、BroadCastReceiver的Context
BroadCastReceiver分为动态注册和静态注册,这里先看下动态注册的过程,在Activity
中动态注册的代码如下:
1.1、动态注册
MyBroadCastReceiver2 myBroadCastReceiver2 = new MyBroadCastReceiver2();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("dynamic_regist");
registerReceiver(myBroadCastReceiver2, intentFilter);
最终会调用Activity
的父类ContextWrapper
的registerReceiver()
,ContextWrapper
是静态代理类,最终会交给目标类ContextImpl
来调用registerReceiver()
,
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
ContextImpl
的registerReceiver()
又会调用其registerReceiverInternal()
,注意调用registerReceiverInternal()
传入的Context
是getOuterContext()
。
getOuterContext()是什么呢?
在Application、Activity、Service
的Context
创建过程中,会创建Application、Activity、Service
的实例以及ContextImpl
的实例,然后调用ContextImpl.setOuterContext(Context context)
将Application、Activity、Service
的实例传入到ContextImpl
中并赋值给其成员变量mOuterContext
。具体可查看
Context关联类和Application Context创建过程
Activity和Service的Context的创建过程
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
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);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
//.....
}
最终会调用mPackageInfo.getReceiverDispatcher()
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<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 (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}
在方法中会创建ReceiverDispatcher
实例并把context
赋值给ReceiverDispatcher
的成员变量mContext
进行保存。
当我们调用sendBroadcast(intent)
发送广播时,会调用ReceiverDispatcher
的performReceive()
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver);
}
}
if (intent == null || !mActivityThread.post(args.getRunnable())) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
mActivityThread.post(args.getRunnable())
会执行Runnable
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
//.......
try {
//....
receiver.onReceive(mContext, intent);
} catch (Exception e) {
//....
}
//....
};
}
可以看到最终会调用receiver.onReceive(mContext, intent)
并把注册时传入的mContext
传递到onReceive()
中。
总结:
- 1、在Activity中动态注册广播,onReceive()中传入的Context是Activity本身。
- 2、在Application中动态注册广播,onReceive()中传入的Context是Application本身。
- 3、在Service中动态注册广播,onReceive()中传入的Context是Service本身。
1.2、静态注册
静态注册在应用安装时由系统完成注册,在分发时ApplicationThread
的scheduleReceiver()
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
updateProcessState(processState, false);
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
r.info = info;
r.compatInfo = compatInfo;
sendMessage(H.RECEIVER, r);
}
发送一个类型为H.RECEIVER
消息到H
中,在handleMessage()
中会调用ActivityThread
的handleReceiver()
private void handleReceiver(ReceiverData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
String component = data.intent.getComponent().getClassName();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
IActivityManager mgr = ActivityManager.getService();
Application app;
BroadcastReceiver receiver;
ContextImpl context;
try {
//创建Application
app = packageInfo.makeApplication(false, mInstrumentation);
//获取Application的ContextImpl
context = (ContextImpl) app.getBaseContext();
if (data.info.splitName != null) {
context = (ContextImpl) context.createContextForSplit(data.info.splitName);
}
java.lang.ClassLoader cl = context.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
//创建Receiver
receiver = packageInfo.getAppFactory()
.instantiateReceiver(cl, data.info.name, data.intent);
} catch (Exception e) {
//....
}
try {
//....
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
//调用Receiver的onReceive
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
} catch (Exception e) {
//....
} finally {
sCurrentBroadcastIntent.set(null);
}
if (receiver.getPendingResult() != null) {
data.finish();
}
}
方法中会创建Receiver
,并调用receiver.onReceive()
,onReceive()
中传入的Context
是通过context.getReceiverRestrictedContext()
生成的,context
是在创建Application
时创建的ContextImpl
实例,所以getOuterContext()
返回的就是Application
本身。
###ContextImpl
final Context getReceiverRestrictedContext() {
if (mReceiverRestrictedContext != null) {
return mReceiverRestrictedContext;
}
return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
}
###ReceiverRestrictedContext
class ReceiverRestrictedContext extends ContextWrapper {
ReceiverRestrictedContext(Context base) {
super(base);
}
}
从上面代码可知getReceiverRestrictedContext()
返回的是以Application
为mBase
的ContextWrapper
,注意这里的Context
并不是Application
,和动态注册是不一样的。
2、ContentProvider的Context
ContentProvider本身不是Context
,但是它有一个成员变量mContext
,是通过构造函数传入的。所以问题就在于ContentProvider
何时创建的。
ContentProvider
的创建是在Application
创建时创建的,Application
的创建逻辑是在ActivityThread.handleBindApplication()
中
private void handleBindApplication(AppBindData data) {
//....
Application app;
try {
//创建Application
app = data.info.makeApplication(data.restrictedBackupMode, null);
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
//创建ContentProvider
installContentProviders(app, data.providers);
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
//....
try {
//调用Application的onCreate()
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
//...
}
} finally {
//....
}
//.....
}
创建过程如下:
- 1、在
LoadedApk
中创建Application
- 2、调用
installContentProviders(app, data.providers)
将创建的Application
传入创建ContentProvider
- 3、调用
Application
的onCreate()
installContentProviders(app, data.providers)
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<ContentProviderHolder> results = new ArrayList<>();
for (ProviderInfo cpi : providers) {
//遍历创建ContentProvider
ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
//....
}
installProvider()
private ContentProviderHolder installProvider(Context context,
ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {
ContentProvider localProvider = null;
IContentProvider provider;
//....
try {
//...
localProvider = packageInfo.getAppFactory()
.instantiateProvider(cl, info.name);
//....
localProvider.attachInfo(c, info);
} catch (java.lang.Exception e) {
//....
}
} else {
provider = holder.provider;
if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
+ info.name);
}
//....
return retHolder;
}
方法中反射创建ConentProvider
,并调用ConentProvider
的attachInfo()
private void attachInfo(Context context, ProviderInfo info, boolean testing) {
if (mContext == null) {
mContext = context;
//....
ContentProvider.this.onCreate();
}
}
在attachInfo
中将传入的context
即Application实例
赋值给ContentProvider
的mContext
。
3、总结
- 1、动态注册的广播:在注册时会创建
ReceiverDispatcher
的实例,并把getOutContext()
赋值给其成员变量mContext
,在收到广播时,会调用对应Receiver
的onReceive()
并将ReceiverDispatcher
的成员变量mContext
传入。所以在Activity、Service、Application
中分别调用registReceiver()
时,onReceive()
中的Context
分别是Activity、Service、Application
的实例。 - 2、静态注册广播:系统完成静态广播的注册,在收到通知时会创建
Receiver
然后调用其onReceive()
并将以Application
为mBase
的ContextWrapper
传入。 - 3、
ContentProvider
本身并不是Context
只不过它有一个成员变量mContext
。ContentProvider
创建之后会调用其attachInfo()
,在方法中将Application
赋值给mContext
。
网友评论