文章目录
Context 的作用
/**
* Interface to global information about an application environment. This is
* an abstract class whose implementation is provided by the Android system. It
* allows access to application-specific resources and classes, as well as
* up-calls for application-level operations such as launching activities,
* broadcasting and receiving intents, etc.
* Context 是一个抽象类,由android系统提供的,它允许获取一些资源和类,并且可以用来启动activity broadcasting,接受 intexts等。。。
*/
public abstract class Context {
public abstract Resources getResources();
/** Return PackageManager instance to find global package information. */
public abstract PackageManager getPackageManager();
/** Return a ContentResolver instance for your application's package. */
public abstract ContentResolver getContentResolver();
public abstract AssetManager getAssets();
public abstract Context getApplicationContext();
// ......
}
- Context 的实现类是 ContextImpl,其内部有很多系统的服务,正是有了这些 Activity 等组件才可以调用系统服务,比如获取系统资源,主题 包管理等。
class ContextImpl extends Context {
@UnsupportedAppUsage
final @NonNull ActivityThread mMainThread;
@UnsupportedAppUsage
final @NonNull LoadedApk mPackageInfo;
@UnsupportedAppUsage
private @Nullable ClassLoader mClassLoader;
private @NonNull Resources mResources;
private Resources.Theme mTheme = null;
@UnsupportedAppUsage
private PackageManager mPackageManager;
}
Context 有几种,它们是怎么被创建的。
- Application、Activity、Service 是有自己的 Context 的
- BroadcastReceiver和ContentProvider是没有自己的 Context 的。
Application
- Application 的 Context 在之前有详细说过创建流程。其中Application的创建是随着应用创建而创建的,进程启动后会执行ActivityThread的 main() 函数,通知 AMS 创建完成,AMS会发送消息通知创建 Application 对象,代码如下:
- Handler 接收到消息后调用 handleBindApplication() ,通过 makeApplication 创建对象,然后调用 callApplicationOnCreate()
private void handleBindApplication(AppBindData data) {
// 获取 data.info 描述应用安装包信息的对象 data.info 就是 LoadedApk
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
//。。。
Application app;
// 通过 makeApplication 方法创建 Application 对象
app = data.info.makeApplication(data.restrictedBackupMode, null);
// 。。。
// 调用 Application 的 onCreate() 函数
mInstrumentation.callApplicationOnCreate(app);
}
- makeApplication() 其中先创建了 ContextImpl 再创建Application时传入了 ContextImpl对象。
public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
final java.lang.ClassLoader cl = getClassLoader();
// 为 Application 创建一个 Context
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// 为 Application 创建对象 传入了 appContext;所以 Application 的 Context 的实现类是 ContextImpl
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
return app;
}
- newApplication()
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
// instantiateApplication 内部通过ClassLoader反射创建 application 对象
Application app = getFactory(context.getPackageName())
.instantiateApplication(cl, className);
// 调用 attch 里面会把 Context 赋值给 mBase ;attach 会调用 attachBaseContext()
app.attach(context);
return app;
}
- app.attach 调用了 attachBaseContext() ,把刚才创建的 ContextImpl 赋值给 mBase;同时可以看到 getBaseContext() 获取的就是 mBase; ContextWrapper 本身就是一个 Context 对象,但是 mBase 也是一个 Context 对象,ContextWrapper 也就是 Application 把 功能都代理给了 mBase 去处理。
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
/**
* @return the base context as set by the constructor or setBaseContext
*/
public Context getBaseContext() {
return mBase;
}
- 总结
- plication 继承自 ContextWrapper 继承自 Context
- 调用顺序:看上面的流程,是先创建的对象,也就是构造函数最先运行,然后调用的 attachBaseContext() 然后调用的 onCreate() 。
- ContextWrapper 中传入了一个 Context ,所有功能都代理给了 mBase 这个 Context
Activity
- Activity 的 Context 是怎么初始化的
activity 启动流程很复杂,最终会调用到 ActivityThread 中的 performLaunchActivity() 方法,看看内部是如何操作的。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// ...
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
// 通过反射创建 Activity 对象
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
// 创建 application 对象,如果创建过则直接返回
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
// 调用 activity 的 attach() 方法,
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);
// 设置主题
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
// 调用 onCreate() 方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
-
Activity 继承自 ContextThemeWrapper ,ContextThemeWrapper 继承自 ContextWrapper 然后继承自 Context 。当Activity 调用 attach 以后还是会调用 attachBaseContext() 调用到的就是 Context 的 attachBaseContext() 依然是和 Applocation 一样通过 mBase 代理。最后会调用 onCreate() 方法。(ContextThemeWrapper 比 ContextWrapper 多了主题的内容,因为 Application 是没有页面展示的所以直接继承了 ContextWrapper)
-
总结
- 继承关系:Activity <— ContextThemeWrapper <— ContextWrapper <— Context
- 调用顺序:先构造器 -> attachBaseContext() -> onCreate()
Service
public abstract class Service extends ContextWrapper{
}
- ActivityThread 的 handleCreateService()
private void handleCreateService(CreateServiceData data) {
Service service = null;
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
Application app = packageInfo.makeApplication(false, mInstrumentation);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
}
- 看上面的代码可以知道 Service 的流程也差不多,结论
先 new 对象,然后 attachBaseContext 然后 onCreate()
BroadcastReceiver
public abstract class BroadcastReceiver {
public abstract void onReceive(Context context, Intent intent);
}
BroadcastReceiver 是没有继承其他的类的,在他的onReceive() 方法中有一个 Context,如果是动态注册则调用者是谁这个 Context 是谁,如果是静态注册的,则 context 就是以 Application 为 mBase 的 ContextWrapper
ContentProvider
public abstract class ContentProvider implements ContentInterface, ComponentCallbacks2 {
@UnsupportedAppUsage
private Context mContext = null;
// 构造函数传入的 mContext ,实际上就是 ApplicationContext
public ContentProvider(
Context context,
String readPermission,
String writePermission,
PathPermission[] pathPermissions) {
mContext = context;
}
}
app = data.info.makeApplication(data.restrictedBackupMode, null);
installContentProviders(app, data.providers);
mInstrumentation.callApplicationOnCreate(app);
上面这段代码 makeApplication 时传入的第二个参数是 Instrumentation 对象,传入的是 null ,所以其内部的 mInstrumentation.callApplicationOnCreate(app); 代码没有走,所以创建完成 application 对象 并调用了 attach 后,创建的 ContentProvider ,然后再调用的 mInstrumentation.callApplicationOnCreate(app); 所以ContentProvider 的 onCreate() 是比 callApplicationOnCreate 先执行的。
问题
- 应用里面有多少Context,不同 Context 之间有什么区别?
应用里 Activity Service 和 Application 有 Context ,所以应用中有多少个这几个组件就有多少个 Context 。区别:Activity 因为有 显示UI,所以继承 ContextThemeWrapper ,其他两个继承 ContextWrapper 。
Activity 里面的 this 和 getBaseContext 有什么区别
this 就是Activity自己的对象,是返回 mBase 对象是 ContextImpl ;
getApplication 和 getApplicationContext 有什么区别
他们俩都是返回 Application 对象,getApplicationContext 是 Context 的抽象函数,但是 getApplication 只有 Activity 和 Service 独有的。因为 Activity 初始化时绑定了 Application ,广播时传入的 Context ,只能获取到 getApplicationContext。
应用组件的构造器、onCreate、attachBaseContext 调用顺序
先 构造器 —> attachBaseContext —> onCreate