Context 是上下文对象,是 Android 常用类 Activity、Service 和 Application 都间接继承 Context ,Context 是一个抽象类,内部定义了很多方法和静态常量,具体实现类是 ContextImpl
ContextImpl 和 ContextWrapper 继承子 Context ,ContextWrapper 内部包含了一个 Context 类型的对象 mBase对象,这个对象指向 ContextImpl ,ContextWrapper 是装饰类,它对 ContextImpl 进行了包装,ContextThemeWrapper、Service、Application 都继承自 ContextWrapper 都可以通过 mBase 来使用 Context 的方法,同时它们也是装饰了,ContextThemeWrapper 中包含了和主题相关的方法
Application Context 创建过程
Android 应用程序启动的最后一步,也是应用程序的入口是 RuntimeInit.java 类通过反射调用其静态 main 方法并创建 ActivityThread 对象
位置:\frameworks\base\core\java\android\app\ActivityThread.java
public static void main(String[] args) {
......
Looper.prepareMainLooper(); // 创建一个消息循环
......
ActivityThread thread = new ActivityThread(); // 创建 ActivityThread 对象
thread.attach(false, startSeq); // 并调用attach方法
......
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
......
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
......
} else {
......
try {
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
.......
}
system 表示是否是系统进程,这个只有在 Framework 进程启动时才会调用到,直接调用了 attachApplication 方法,通过 Binder进程间通讯的方式,向 AMS 发送了一个消息
位置:\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq); // 调用 attachApplicationLocked 方法
Binder.restoreCallingIdentity(origId);
}
}
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
......
if (app.isolatedEntryPoint != null) {
// This is an isolated process which should just call an entry point instead of
// being bound to an application.
thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
} else if (app.instr != null) {
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
}
......
return true;
}
可以看到这里面又调用了 IApplicationThread.bindApplication 方法,IApplicationThread 是 ActivityThread 中 ApplicationThread binder 对象的客户端
位置:\frameworks\base\core\java\android\app\ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
......
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, boolean autofillCompatibilityEnabled) {
if (services != null) {
if (false) {
// Test code to make sure the app could see the passed-in services.
for (Object oname : services.keySet()) {
if (services.get(oname) == null) {
continue; // AM just passed in a null service.
}
String name = (String) oname;
// See b/79378449 about the following exemption.
switch (name) {
case "package":
case Context.WINDOW_SERVICE:
continue;
}
if (ServiceManager.getService(name) == null) {
Log.wtf(TAG, "Service " + name + " should be accessible by this app");
}
}
}
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
data.autofillCompatibilityEnabled = autofillCompatibilityEnabled;
sendMessage(H.BIND_APPLICATION, data);
}
......
}
最后调用了ActivityThread.sendMessage(),sendMessage 发送了一个 Handler 的异步消息,最后被 handleMessage 方法处理
private void handleBindApplication(AppBindData data) {
......
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
......
final InstrumentationInfo ii;
// 创建 Instrumentation
if (data.instrumntationName != null) {
try {
ii = new ApplicationPackageManager(null, getPackageManager())
.getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
"Unable to find instrumentation info for: " + data.instrumentationName);
}
// Warn of potential ABI mismatches.
if (!Objects.equals(data.appInfo.primaryCpuAbi, ii.primaryCpuAbi)
|| !Objects.equals(data.appInfo.secondaryCpuAbi, ii.secondaryCpuAbi)) {
Slog.w(TAG, "Package uses different ABI(s) than its instrumentation: "
+ "package[" + data.appInfo.packageName + "]: "
+ data.appInfo.primaryCpuAbi + ", " + data.appInfo.secondaryCpuAbi
+ " instrumentation[" + ii.packageName + "]: "
+ ii.primaryCpuAbi + ", " + ii.secondaryCpuAbi);
}
mInstrumentationPackageName = ii.packageName;
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationSplitAppDirs = ii.splitSourceDirs;
mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
mInstrumentedAppDir = data.info.getAppDir();
mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
mInstrumentedLibDir = data.info.getLibDir();
} else {
ii = null;
}
.......
try {
app = data.info.makeApplication(data.restrictedBackupMode, null); // 创建 Application 对象
// Propagate autofill compat state
app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
mInitialApplication = app;
.......
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
|| StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
StrictMode.setThreadPolicy(savedPolicy);
}
}
......
}
handleBindApplication 方法首先通过反射创建了 Instrumentation 对象,并执行了 init 方法初始化,然后调用 LoadedApk 类的 makeApplication 方法来创建一个 Application 对象,在 LoadedApk 类中会把创建的 Application 对象保存在 mApplication 变量中,并返回这个变量赋值给 ActivityThread 类中的 mInitialApplication 变量
位置:\frameworks\base\core\java\android\app\LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
// 检查是否已经创建
if (mApplication != null) {
return mApplication;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
Application app = null;
// 设置 Application 的类名
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
// 创建 Application 及其 Context
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
// 1.创建Context
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
// 2.创建 Application
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
// 3.将两个对象关联起来
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
// 4.保存创建的Application
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
// 调用 Application 中的 onCreate() 方法
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
.......
return app;
}
1.首先调用 ContextImpl.createAppContext 静态方法创建 ContextImpl 实例
2.调用 newApplication 方法并传入 ContextImpl 实例和之前设置的 appClass,来创建该类名对应的一个 Application实例,在 newApplication 方法内部,创建完 Application 实例后,会调用其 attach 方法并传入 ContextImpl 实例,在 attach 方法中又会调用其父类 ContextWrapper(装饰类) 中的 attachBaseContext() 方法,将 ContextImpl 对象设置给内部实例变量 mBase, 这样 Application 内部就持有了Context的实现类ContextImpl实例
位置:\frameworks\base\core\java\android\app\Instrumentation.java
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance(); // 创建 Application 类,相当于 new 关键字
app.attach(context); // 调用 Application 的 attach 方法
return app;
}
位置:\frameworks\base\core\java\android\app\Application.java
/* package */ final void attach(Context context) {
attachBaseContext(context); // 直接调用 attachBaseContext 方法,attachBaseContext 方法是在其父类 ContextWrapper 实现的
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
位置:\frameworks\base\core\java\android\content\ContextWrapper.java
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base; // 将 ContextImpl 对象设置给内部实例变量 mBase
}
3.最后调用 ContextImpl 的实例方法 setOuterContext,传入这个 Application 实例,这样 ContextImpl 实例也会持有 Context 的包装类 ContextWrapper 实例
4.创建完一个 Application 对象后,将其保存在 mApplication 实例变量中,由于一个应用程序进程中的 LoadedApk 对象也是一个单例,因此一个进程中只能创建一个 Application 对象。
Application 得到 Context
都知道得到 Application 的 Context 是通过 getApplicationContext() 方法获得到的,这个方法是在 Application 的父类 ContextWrapper 中实现的
Activity 创建 Context
从上面得知,创建 Application 对象是通过 ActivityManagerService 中的 attachApplicationLocked 方法中的 thread.bindApplication 方法去创建并绑定到 AMS 中,在 thread.bindApplication 之后会调用 mStackSupervisor.attachApplicationLocked(app) 方法去启动应用的 Activity,详细见这篇文章:https://blog.csdn.net/weixin_44128558/article/details/132140588 之后经过层层调用会调用到 ActivityThread 中的 performLaunchActivity 方法
位置:\frameworks\base\core\java\android\app\ActivityThread.java
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
ContextImpl appContext = createBaseContextForActivity(r); //1.创建 Context
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent); // 2.创建一个新的Activity
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
}
......
try {
......
if (activity != null) {
......
appContext.setOuterContext(activity); //3.将Activity 和 Context 关联起来
activity.attach(appContext, this, getInstrumentation(), r.token, //4.调用attach 将 ContextImpl 对象设置给内部实例变量 mBase
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
......
if (r.isPersistable()) { // 调用 activity 的 OnCreate 方法
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
......
r.activity = activity; //5.保存创建的Activity
}
......
}
.......
return activity;
}
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
......
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
......
return appContext;
}
可见,与 Application 创建 Context 流程类似
1.直接调用 createBaseContextForActivity 方法返回一个 ContextImpl 对象
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
......
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
......
return appContext;
}
createBaseContextForActivity 方法里调用 ContextImpl.createActivityContext 静态方法创建 ContextImpl 实例并返回
位置:\frameworks\base\core\java\android\app\ContextImpl.java
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
Configuration overrideConfiguration) {
......
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
activityToken, null, 0, classLoader);
......
final ResourcesManager resourcesManager = ResourcesManager.getInstance();
// Create the base resources for which all configuration contexts for this Activity
// will be rebased upon.
context.setResources(resourcesManager.createBaseActivityResources(activityToken,
packageInfo.getResDir(),
splitDirs,
packageInfo.getOverlayDirs(),
packageInfo.getApplicationInfo().sharedLibraryFiles,
displayId,
overrideConfiguration,
compatInfo,
classLoader));
context.mDisplay = resourcesManager.getAdjustedDisplay(displayId,
context.getResources());
return context;
}
这里真正创建了 Context
2. 调用 newActivity 方法并传入 ContextImpl 实例,实际调用的是 AppComponentFactory 的 instantiateActivity() 方法,该方法通过反射方式创建 Activity
位置:frameworks\base\core\java\android\app\Instrumentation.java
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null;
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
位置:frameworks\base\core\java\android\app\AppComponentFactory.java
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass(className).newInstance();
}
3. 与 Application 相同,调用 ContextImpl 的实例方法 setOuterContext,传入这个 Activity 实例,这样 ContextImpl 实例也会持有 Context 的包装类 ContextWrapper 实例
4. 再调用 Activity 的 attach ,也 Application 类似,该方法中会调用其父类 ContextWrapper 中的 attachBaseContext 方法,将 ContextImpl 对象设置给内部实例变量 mBase
位置:\frameworks\base\core\java\android\app\Activity.java
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, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context); // 将 ContextImpl 对象设置给内部实例变量 mBase
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window, activityConfigCallback); //创建 PhoneWindow 应用程序的窗口
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(); //创建刷新ui的线程
......
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(); // 得到 WindowManager 并赋给 mWindowManager 成员变量,这样 Activity 可以通过 getWindowManager 方法来获得 WindowManager
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
enableAutofillCompatibilityIfNeeded();
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
if (newBase != null) {
newBase.setAutofillClient(this);
}
}
首先调用 attachBaseContext 方法,attachBaseContext 方法中又直接调用其父类 (ContextThemeWrapper) 的 attachBaseContext 方法
ContextThemeWrapper 又会调用其父类 (ContextThemeWrapper) 的 attachBaseContext 方法,将 ContextImpl 对象设置给内部实例变量 mBase (与上面 Application 相同)
之后会创建 PhoneWindow ,PhoneWindow 会接受很多事件,比如点击,菜单弹出,屏幕焦点变化等,这些都会转发给与 PhoneWindow 关联的 Activity,通过 Window.Callback 回调接口实现,当前的 Activity 通过 Window 的 setCallback 方法 传递给 PhoneWindow
5.创建完一个 Activity 对象后,将其保存在 mApplication 实例变量中
Service 创建 Context
Service 的 Context创建过程与 Activity 的 Context 创建过程类似,是在 Service 的启动过程中被创建,Service 是通过 ActiviytThread 的内部类 ApplicationThread 调用 scheduleCreateService 方法来启动
与 Activity 类似,最后将创建的 ContextImpl 一路传递到 Context