Context经常称为”上下文”
关系如图:
可以看出Context只是个抽象类,而实现类则是ContextIml
这里主要是使用了装饰者模式
基本介绍
ContextIml
Context的实现类,Context的相关方法的具体实现就是该类提供
ContextWrapper
只是对Context的一种包装,里面含有了个mBase
1 2 3 4 5 6 7 8 |
public class ContextWrapper extends Context { Context mBase; //该属性指向一个ContextIml实例,一般在创建Application、Service、Activity时赋值 //创建Application、Service、Activity,会调用该方法给mBase属性赋值 public ContextWrapper(Context base) { mBase = base; } ... |
ContextThemeWrapper
ContextThemeWrapper继承ContextWrapper 主要是包含了主题(Theme)相关的接口
可以看出Activity是继承这个类需要主题,而Service是没有继承的
Context的创建时期
情况有如下几种情况:
- 创建Application 对象时, 而且整个App共一个Application对象
- 创建Service对象时
- 创建Activity对象时
总Context实例个数 = Service个数 + Activity个数 + 1(Application对应的Context实例)
创建Application关联Context
创建Application的时候可以在ActivityThread中
1 2 3 4 5 6 7 8 9 10 11 |
private void handleBindApplication(AppBindData data) { ... final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. // 调用了Application类中的makeApplication方法 Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; .... } |
Application的makeApplication方法中创建了一个ContextIml
1 2 3 4 5 6 7 8 9 10 |
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { ... // 可见这里新创建了ContextIml类,并传下去 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); ... } |
最后在Instrumentation中的newApplication方法调用了attach方法关联
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Application app = (Application)clazz.newInstance(); // 调用了attach方法,把ContextIml关联 app.attach(context); return app; } //Application的attach方法 /* package */ final void attach(Context context) { // 关联进去 attachBaseContext(context); mLoadedApk = ContextImpl.getImpl(context).mPackageInfo; } |
创建Activity关联Context
Activity创建在ActivityThread中调用
主要是调用了performLaunchActivity方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
... // 先得到activity Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(); if (r.state != null) { r.state.setClassLoader(cl); } ... //如果Activity不为空,则创建了一个appContext if (activity != null) { Context appContext = createBaseContextForActivity(r, activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mCompatConfiguration); if (r.overrideConfig != null) { config.updateFrom(r.overrideConfig); } ... //最后调用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); } |
关于createBaseContextForActivity方法:
1 2 3 4 5 6 7 |
... //这里还是创建了一个ContextIml ContextImpl appContext = ContextImpl.createActivityContext( this, r.packageInfo, r.token, displayId, r.overrideConfig); appContext.setOuterContext(activity); Context baseContext = appContext; ... |
创建Service关联Context
Service的创建也是调用了Activity中的handleCreateService的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
private void handleCreateService(CreateServiceData data) { ... //也是先找到这个Service Service service = null; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to instantiate service " + data.info.name + ": " + e.toString(), e); } } ... // 最后进行创建ContextIml,然后attach起来 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); service.onCreate(); ... } |
小结:
通过对ContextImp的分析可知,其方法的大多数操作都是直接调用其属性mPackageInfo(该属性类 型为PackageInfo)的相关方法而来。
这说明ContextImp是一种轻量级类,而PackageInfo才是真正重量级的类。而一个App里的 所有ContextIml实例,都对应同一个packageInfo对象。