Android 面试:一个进程有多少个 -Context- 对象?看似初级的问题,答的好的人确不多
目录
作者:彭旭锐链接:https://www.jianshu.com/p/51d63a1ffb95
1. Context 继承关系
Context是一个抽象类,具体的实现类有Application、Activity、Service与ContextImpl。为方便区分,通常也称为ApplicationConext、ActivityContext与ServiceContext,具体 UML 类图如下:
可以看到,除了我们熟悉的Application、Activity、Service,继承关系上还有ContextWrapper与ContextThemeWrapper,它们的作用 & 职责如下:
ContextWrapper定义:
Context包装类作用:持有基础对象的引用
(mBase),并且实现了Context接口,将所有方法调用请求转发给基础对象
// ContextWrapper.java
Context mBase;
public ContextWrapper(Context base) {mBase = base;}
// 【分析点 1:绑定基础对象(见 todo)】protected void attachBaseContext(Context base) {if (mBase != null) {throw new IllegalStateException("Base context
already set");}mBase = base;}
@Overridepublic void startActivity(Intent intent) {// 转发给 mBasemBase.startActivity(intent);}
ContextThemeWrapper定义:
Context包装类【todo】
2. Application 对象
我们都知道,在启动四大组件(Activity、Service、ContentProvider, BroadcastReceiver)时,如果对应的进程未启动,就需要先创建进程,相应地也会创建一个Application对象。简单来说:
在
system_server进程,通过AMS#getProcessRecordLocked(...)获取进程信息(ProcessRecord);若不存在,则调用
AMS#startProcessLocked(...)创建进程在
Zygote孵化目标进程之后,在目标进程反射执行ActivityThread#main(),并最终在ActivityThread#handleBindApplication(...)中创建Application对象
// ActivityThread.java
Application mInitialApplication;final ArrayList<Application> mAllApplications = new ArrayList<Application>();
private void handleBindApplication(AppBindData data) {// ...Application app;// data.info 为 LoadedApk.javaapp = data.info.makeApplication(data.restrictedBackupMode, null);// ...mInitialApplication = app;// ...}
// LoadedApk.java
private Application mApplication;
public Application makeApplication(...) {// 创建基础对象 ContextImplContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);// 反射调用创建 Application 对象 app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);// ContextImpl 也持有包装类 ApplicationappContext.setOuterContext(app);// 保存创建的 Application 对象 mActivityThread.mAllApplications.add(app);mApplication = app;}
// Instrumentation.java
public Application newApplication(ClassLoader cl, String className, Context context) {// 反射调用创建 Application 对象 Application app = getFactory(context.getPackageName()).instantiateApplication(cl, className);app.attach(context);return app;}
// Application.javafinal void attach(Context context) {// 设置包装类 Application 的基础对象 attachBaseContext(context);mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;}
总结要点如下:
一个
Application对象相当于存在两个Context对象(代理对象与基础对象)Application对象与ContextImpl对象相互引用
3. Activity 对象
这一节我们来看Activity对象的创建过程,简单来说:
创建
Application对象之后,最后在ActivityThread#handleLaunchActivity(...)中创建Activity对象
// ActivityThread.java
public Activity handleLaunchActivity(...) {// ...final Activity a = performLaunchActivity(r, customIntent);// ...}
private Activity performLaunchActivity(...) {// ...// 创建基础对象 ContextImplContextImpl appContext = ContextImpl.createActivityContext(...);// 反射调用创建 Activity 对象 Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);











评论