CSDN话题挑战赛第2期
参赛话题:面试宝典
1. 应用中一共多少个实例?
首先我们将Context的继承结构梳理一下
通过查看Context的继承结构,我们可以看到
Context的直接子类是ContextWrapper
,我们看下ContextWrapper的初始化相关方法,我们用到的几个子类实现分别有Application
、Service
、Activity
//ContextWrapper
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
构造方法传递的都是null,另外一个方法attachBaseContext
也是用来初始化mBase
的,我们分别查看一下各个具体子类的相关实现
Application
frameworks/base/core/java/android/app
-> ActivityThread.performLaunchActivity()
-> LoadedApk.makeApplication()
-> Instrumentation.newApplication()
-> Application.attach()
-> ContextWrappter.attachBaseContext()
// 创建ContextImpl实例步骤可参考activity下ContextImpl实例创建步骤
// 结论是通过 new ContextImpl方式创建实例
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
// 反射构建application对象
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
app.attach(context);
return app;
}
Service
framework/base/services/core/java/com/android/server/am
ActivityManagerService
-> startService()
ActiveServices
-> startServiceLocked()
-> startServiceInnerLocked()
-> realStartServiceLocked()
-> ActivityThread.scheduleCreateService()
-> handleCreateService()
-> Service.attach()
-> ContextWrappter.attachBaseContext()
// ActivityThread
private void handleCreateService(CreateServiceData data){
//...
Service service = null;
//...
// 反射方式创建service对象
service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent);
// 创建ContextImpl对象( ContextImpl context = new ContextImpl())
ContextImpl context = ContextImpl.getImpl(service.createServiceBaseCotnext(this,packageInfo));
//...
// service绑定ContextImpl
service.attach(context, this, data.info.name, data.token, app,ActivityManager.getService());
service.onCreate();
}
Activity
frameworks/base/core/java/android/app
-> ActivityThread.performLaunchActivity()
-> Activity.attach()
-> attachBaseContext()
-> ContextThremeWrapper.attachBaseContext()
-> ContextWrappter.attachBaseContext()
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//...
// 创建ContextImpl实例
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try{
// 创建activity实例
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
}
//...
try{
// activity绑定contextImpl
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
r.assistToken, r.shareableActivityToken);
//...
// 回调activity的onCreate()方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
}
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
// ContextImpl impl = new ContextImpl(),通过new的方式创建实例
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
//...
return appContext;
}
查看上述几个具体实现类的ContextImpl
的实例绑定,我们可以得出一个应用总共的ContextImpl
实例个数为:1(Application) + Activity个数 + Service个数
2. 如何获取ContextImpl实例?
查看ContextImpl类,我们知道该类不是public,应用程序是无法获取到该类并且通过new的形式创建实例。我们可以通过getImpl的方法,进行反射获取
static ContextImpl getImpl(Context context) {
Context nextContext;
while ((context instanceof ContextWrapper) &&
(nextContext=((ContextWrapper)context).getBaseContext()) != null) {
context = nextContext;
}
return (ContextImpl)context;
}
try{
Class<?> clazz=Class.forName("android.app.ContextImpl");
Method method=clazz.getDeclaredMethod("getImpl",Context.class);
method.setAccessible(true);
// 获取ContextImpl的实例
Object mContextImpl=method.invoke(null,this);
}