借鉴:Android应用Context详解及源码解析
http://www.androidchina.net/3853.html http://www.jianshu.com/p/f24707874b04
1、它描述的是一个应用程序环境的信息,即上下文。 2、该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类(ContextIml类)。 3、通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent信息 等。
先介绍一下context 类的继承关系,之后的讲解可以结合这张图来分析:
摘自:http://blog.csdn.net/yanbober/article/details/45967639
ContextImpl:该类实现了Context类的所有功能。
/** * Common implementation of Context API, which provides the base * context object for Activity and other application components. */ class ContextImpl extends Context { private Context mOuterContext; ...... }ContextWrapper
/** * Proxying implementation of Context that simply delegates all of its calls to * another Context. Can be subclassed to modify behavior without changing * the original Context. */ public class ContextWrapper extends Context { Context mBase; public ContextWrapper(Context base) { mBase = base; } /** * Set the base context for this ContextWrapper. All calls will then be * delegated to the base context. Throws * IllegalStateException if a base context has already been set. * * @param base The new base context for this wrapper. */ protected void attachBaseContext(Context base) { if (mBase != null) { throw new IllegalStateException("Base context already set"); } mBase = base; } ...... } ContextThemeWrapper:/** * A ContextWrapper that allows you to modify the theme from what is in the * wrapped context. */ public class ContextThemeWrapper extends ContextWrapper { ...... }
Activity : public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback { ...... } Service public abstract class Service extends ContextWrapper implements ComponentCallbacks2 { ...... } Application public class Application extends ContextWrapper implements ComponentCallbacks2 { ...... }
先来说,这些之后都会结合源码详细讲解(只是为了自己方便才先写出来)
context 是一个抽象类,提供类很多抽象的方法 contextImpl 是context的实现类 继承context ,主要对抽象方法具体化,所有的context的具体操作都在这里。 contextWrapper 是对context的包装类 继承context, contextThemeWrapper 是有主题的context,因为activity有主题(就是我们在Manifest里面配的),所以activity extendscontextThemeWrapper contextWrapper 有一个特别重要的变量 Context mBase,一般在启动activity、service、application 的时候通过先attachBaseContext ,把new 出来contextImpl赋值给mBase 之后,在通过回调 执行 各自的生命周期。 /** * Set the base context for this ContextWrapper. All calls will then be * delegated to the base context. Throws * IllegalStateException if a base context has already been set. * * @param base The new base context for this wrapper. */ protected void attachBaseContext(Context base) { if (mBase != null) { throw new IllegalStateException("Base context already set"); } mBase = base; } 源码中是将 contextImpl--->base,也就是在contextWrapper中,通过base 来操作 contextImpl 最终的操作都是在 contextImpl 实现的 activity、service、application 都属于context; APP Context总数 = Application数(1) + Activity数(Customer) + Service数(Customer); app中startActivity、startService、sendBroadcast 其实都是context的方法,这样看,四大组件中三个和context相关,由此可见context是多么的重要
Context的实现是ContextImpl,Activity与Application和Service的创建都是在ActivityThread中完成的,重点分析各context的创建过程。
通过startActivity启动一个新的Activity时系统会回调ActivityThread的handleLaunchActivity()方法,内部在调用performLaunchActivity创建activity,然后回调onCreate等方法,所以activity的contextImpl在performLaunchActivity中
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ...... //已经创建好新的activity实例 if (activity != null) { //创建一个Context对象 Context appContext = createBaseContextForActivity(r, activity); ...... //将上面创建的appContext传入到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); ...... } ...... return activity; }
createBaseContextForActivity()创建context,再通过attach,把appContext传入activity中。
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) { //实质就是new一个ContextImpl对象,调运ContextImpl的有参构造初始化一些参数 ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token); //特别特别留意这里!!! //ContextImpl中有一个Context的成员叫mOuterContext,通过这条语句就可将当前新Activity对象赋值到创建的ContextImpl的成员mOuterContext(也就是让ContextImpl内部持有Activity)。 appContext.setOuterContext(activity); //创建返回值并且赋值 Context baseContext = appContext; ...... //返回ContextImpl对象 return baseContext; }
activity.attach
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor) { //特别特别留意这里!!! //与上面createBaseContextForActivity方法中setOuterContext语句类似,不同的在于: //通过ContextThemeWrapper类的attachBaseContext方法,将createBaseContextForActivity中实例化的ContextImpl对象传入到ContextWrapper类的mBase变量,这样ContextWrapper(Context子类)类的成员mBase就被实例化为Context的实现类ContextImpl attachBaseContext(context); ...... }
Activity通过ContextWrapper的成员mBase来引用了一个ContextImpl对象,这样,Activity组件以后就可以通过这个ContextImpl对象来执行一些具体的操作(启动Service等);
同时ContextImpl类又通过自己的成员mOuterContext引用了与它关联的Activity,这样ContextImpl类也可以操作Activity。
3.3Application中ContextImpl实例化源码分析
当我们写好一个APP以后每次重新启动时都会首先创建Application对象(每个APP都有一个唯一的全局Application对象,与整个APP的生命周期相同)。
创建Application的过程也在ActivityThread类的handleBindApplication()方法完成相关数据操作(具体关于ActivityThread调运handleBindApplication时机等
细节分析与上面Activity雷同,后边文章会做分析)。而ContextImpl的创建是在该方法中调运LoadedApk类的makeApplication方法中实现,
LoadedApk类的makeApplication()方法中源代码如下:
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) { //只有新创建的APP才会走if代码块之后的剩余逻辑 if (mApplication != null) { return mApplication; } //即将创建的Application对象 Application app = null; String appClass = mApplicationInfo.className; if (forceDefaultAppClass || (appClass == null)) { appClass = "android.app.Application"; } try { java.lang.ClassLoader cl = getClassLoader(); if (!mPackageName.equals("android")) { initializeJavaContextClassLoader(); } //不做过多解释,创建一个Context对象 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); //将Context传入Instrumentation类的newApplication方法 app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); //特别特别留意这里!!! //ContextImpl中有一个Context的成员叫mOuterContext,通过这条语句就可将当前新Application对象赋值到创建的ContextImpl的成员mOuterContext(也就是让ContextImpl内部持有Application)。 appContext.setOuterContext(app); } catch (Exception e) { ...... } ...... return app; }
Instrumentation.newApplication方法
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return newApplication(cl.loadClass(className), context); }
newApplication
static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { ...... //继续传递context app.attach(context); return app; }
attach
final void attach(Context context) { //特别特别留意这里!!! //与上面makeApplication方法中setOuterContext语句类似,不同的在于: //通过ContextWrapper类的attachBaseContext方法,将makeApplication中实例化的ContextImpl对象传入到ContextWrapper类的mBase变量,这样ContextWrapper(Context子类)类的成员mBase就被实例化为Application的实现类ContextImpl attachBaseContext(context); ...... }