完全剖析Android上下文环境Context

Context简介

从谷歌对Context的介绍可知:

  1. Context是一个应用程序环境信息的接口,表示上下文的意思
  2. Context是一个抽象类,Android系统提供了该抽象类的具体实现类,即ContextImpl类,这里用到了一种代理模式
  3. 通过Context类获取应用程序的资源和类,也可以进行应用程序的操作,如启动Activity、发送广播、接受Intent信息等

应用程序中Context的总数目为:
总Context个数 = Activity个数 + Service个数 + 1(Application Context)

由于Service类和Activity类都是继承Context的,应用程序被启动后,还会为应用程序创建一个全局的Application对应的Context对象。Context是基类,Activity、Service、Application都是间接继承它。ContextImpl类继承了COntext,它才是Context的真正实现。ContextWrapper类中的变量mBase是一个ContextImpl对象,指向真正的实现类ContextImpl,而ContextImpl类中的mOuterContext是一个Context对象,指向相对应的Activity或Service或Application。
Context关系图如下所示:

Application Context创建过程

创建Application Context

当一个应用程序被启动之后,应用程序里就有一个Application Context对象,这个Context对象通过LoadedApk.java的makeApplication()方法创建。

当应用程序进程启动之后,Android系统Framework框架里的ActivityManagerService核心服务会调入应用程序客户端ActivityThread类的scheduleLaunchActivity()方法里。从该方法开始分析Context的创建过程,先看看ActivityThread类的scheduleLaunchActivity()方法。

1
2
3
4
5
6
7
8
9
10
11
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,int procState, Bundle state, List<ResultInfo> pendingResults,List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
.....
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
....
sendMessage(H.LAUNCH_ACTIVITY, r);
}

schduleLaunchActivity()方法通过ActivityManagerService服务调用。首先,这个对象会生成一个内部类ActivityClientRecord对象r,并且把它里面的变量token赋值。这个token变量是AMS中ActivityRecord类里面的一个binder对象,这个token对象会同时传到应用程序ActivityThread和WindowManagerService(WMS),关于token此处不继续展开。scheduleLaunchActivity()方法会通过H类发送一个LAUNCH_ACTIVITY消息,H类继承于Handler,是ActivityThread的内部类,主要用于在ActivityThread内部分发消息。看看H类的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
.....
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
......
}
}
}

在H类的handleMessage()收到消息后主要调用了handleLaunchActivity()方法继续处理:

1
2
3
4
5
6
7
8
9
10
11
12
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
.......
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
......
}
......
}

handleLaunchActivity()方法首先调用了performLaunchActivity()方法,这个方法主要用于创建Application Context和Activity Context。之后调用handleResumeActivity()方法主要是来进入Activity的生命周期onResume()方法。下面看看performLaunchActivity()方法创建Application Context的过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
.......
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
.....
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
.....
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
....
mInstrumentation.callActivityOnCreate(activity, r.state);
....
}
}
}

变量packageInfo是一个LoadApk类型的对象,通过调用它的makeApplication()方法来创建Application Context。在该方法中,如果变量Activity不为空,还会调用createBaseContextForActviity()方法来创建Activity上下文Context。下面是LoadApk类中的makeApplication()方法来创建Application Context:

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
31
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
.....
try {
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = new ContextImpl();
appContext.init(this, null, mActivityThread);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
.......
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
......
}
}
return app;
}

变量mApplication是LoadApk类中的全局变量,它是一个Application对象。假设第一次启动应用程序时,Application Context还没创建,会先创建一个ContextImpl实例,然后会通过ActivityThread的变量mInstrumentation(Instrumentation类型对象)的方法newApplication()创建一个Application对象app。然后把app对象通过setOuterContext()方法赋值给ContextImpl的mOuterContext变量,最后把该app对象赋值给LoadApk的人全局变量mApplication。

下面看看Instrumentation类的newApplication方法:

1
2
3
4
5
6
7
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}

newApplication()方法首先会创建一个Application类型的对象app,然后调用它的attach()方法将传进来的ContextImpl对象赋值给ContextWrapper类的mBase对象,最后返回app。
下面看看Application类的attach()方法:

1
2
3
4
/* package */ final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

1
2
3
4
5
6
7
8
9
10
11
public class ContextWrapper extends Context {
Context mBase;
.....
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
....
}

attach()方法调用父类的attachBaseContext()方,将ContextImpl对象赋值给ContextWrapper类的mBase对象。

回到前面的makeApplication()方法中,这个过程之后会调用setOuterContext()方法将Application对象赋值给ContextImpl的mOuterContext变量:

1
2
3
4
5
6
7
8
class ContextImpl extends Context {
private Context mOuterContext;
......
final void setOuterContext(Context context) {
mOuterContext = context;
}
....
}

至此,Application Context的创建过程就介绍完毕。

获取·Application Context

在应用程序中,可以直接通过getApplicationContext()方法来获得ApplicationContext。而这个调用,会进入到框架层ContextWrapper类的getApplicationContext()方法中:

1
2
3
4
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}

变量mBase是COntextImpl类的对象,此处调用getApplicationContext()方法进入COntextImpl类的getApplicationContext()方法中:

1
2
3
4
5
@Override
public Context getApplicationContext() {
return (mPackageInfo != null) ?
mPackageInfo.getApplication() : mMainThread.getApplication();
}

变量mPackageInfo是一个LoadApk对象,而变量mMainThread是一个ActivityThread对象。由于应用程序已经启动,mPackageInfo变量不为空,于是调用LoadApk的个体Application方法:

1
2
3
Application getApplication() {
return mApplication;
}

直接返回Application类型的mApplication对象,在前面LoadApk.java的makeApplication()方法中创建的。

Activity Context创建过程

前面的创建调用过程和Application的创建基本一致,都是由AMS服务调用scheduleLaunchActivity()方法开始,到performLaunchActivity()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
.......
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
.....
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
.....
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
....
mInstrumentation.callActivityOnCreate(activity, r.state);
....
}
}
}

大致流程可分为一下几个步骤:

  1. 变量cl是一个ClassLoader对象,即类加载器。通过Instrumentation对象的newActivity()方法创建一个Activity实例。

    1
    2
    3
    4
    5
    6
    public Activity newActivity(ClassLoader cl, String className,
    Intent intent)
    throws InstantiationException, IllegalAccessException,
    ClassNotFoundException {
    return (Activity)cl.loadClass(className).newInstance();
    }
  2. 接着performLaunchActivity()方法调用createBaseContextForActivity()方法来创建ContextImpl类型对象appContext:

    1
    2
    3
    4
    5
    6
    7
    8
    private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
    .....
    ContextImpl appContext = ContextImpl.createActivityContext(
    this, r.packageInfo, r.token, displayId, r.overrideConfig);
    appContext.setOuterContext(activity);
    Context baseContext = appContext;
    ......
    }

通过调用ContextImpl的createActivityContext()方创建出一个ContextImpl实例,并通过ContextImpl的setOuterContext()方法将前面创建的activity实例对象赋值给ContextImpl类的mOuterContext变量。如下所示:

1
2
3
4
5
6
7
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, IBinder activityToken, int displayId,
Configuration overrideConfiguration) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread, packageInfo, activityToken, null, 0,
null, overrideConfiguration, displayId);
}

1
2
3
4
5
6
7
8
class ContextImpl extends Context {
private Context mOuterContext;
......
final void setOuterContext(Context context) {
mOuterContext = context;
}
....
}
  1. 接着performLaunchActivity()方法就调用Activity的attach()方法来讲前面所创建的ContextImpl对象appContext保存在Activity内部:

    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
    31
    32
    33
    34
    35
    36
    37
    38
    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,
    Window window) {
    //调用父类的方法设置mBase,与上文Application类似
    attachBaseContext(context);
    mFragments.attachHost(null /*parent*/);
    mWindow = new PhoneWindow(this, window);
    mWindow.setWindowControllerCallback(this);
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
    mWindow.setSoftInputMode(info.softInputMode);
    }
    if (info.uiOptions != 0) {
    mWindow.setUiOptions(info.uiOptions);
    }
    mUiThread = Thread.currentThread();
    mMainThread = aThread;
    ........
    mWindow.setWindowManager(
    (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
    mToken, mComponent.flattenToString(),
    (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    if (mParent != null) {
    mWindow.setContainer(mParent.getWindow());
    }
    mWindowManager = mWindow.getWindowManager();
    mCurrentConfig = config;
    }
  2. 最后performLaunchActivity()方法又通过调用mInstrumentation对象的方法callActivityOnCreate()来通知Activity进入它的生命周期onCreate()方法:

    1
    2
    3
    4
    5
    6
    public void callActivityOnCreate(Activity activity, Bundle icicle,
    PersistableBundle persistentState) {
    prePerformCreate(activity);
    activity.performCreate(icicle, persistentState);
    postPerformCreate(activity);
    }

通过调用Activity的performCreate()方法:

1
2
3
4
5
6
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}

根据java的多态性,onCreate()会进入Activity子类的onCreate()方法。

Service Context的创建过程

service在启动过程中,ActivityManagerService服务会被调用到ActivityThread类中,最后进入ActivityThread的handleCreateService()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void handleCreateService(CreateServiceData data) {
......
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
......
}
try {
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();
....
} catch (Exception e) {
.....
}
}

handleCreateService()方法首先加载一个ClassLoader对象,通过这个对象加载Service对象,构建Service实例。接着通过ContextImpl的createAppContext()方法创建ContextImpl类型实例context。然后通过这个ContextImpl类型实例context调用setOuterContext()方法把Service对象赋值给ContextImpl的mOuterContext变量。最后又通过调用Service的attach()方法把ContextImpl实例context赋值给ContextWrapper类的mBase变量。该过程和上面的两种基本相似,这里就不一一展开咯。。。。。