前言
在 Android 开发中,我们随处看见Context,但你知道它到底是代表了什么吗?
Context,即上下文,是Android中常用的类之一。Android开发中,从启动 Activity,访问资源,再到弹出一个Toast,创建一个Dialog,Context 实可谓无处不在。
本篇文章将较为详细的为大家介绍一下Context,帮助大家更加深入的理解Android程序员的这一“老朋友”。
…
1 理解上下文
Context 也就是上下文对象,是 Android 常用的类。
Context 意为上下文,是一个应用程序环境信息的接口。
使用场景:
- 使用 Context 调用方法,比如启动 Activity、访问资源、调用系统级服务等。
- 调用方法时传入 Context, 比如弹出 Toast、 创建 Dialog 等。
Activity 、 Service 和 Application 都间接地继承自 Context 。
一个应用程序进程中有多少个 Context ,这个数量等于 Activity 和 Service 的总个数加 1,1指的是 Application 的数量。
Context 是一个抽象类,它的内部定义了很多方法以及静态常量,它的具体实现为 ContextImpl。
和Cotext 相关联的类, 除了 ContextImpl ,还有 ContextWrapper、ContextThemeWrapper 和 Activity 等。
ContextImpl 和 ContextWrapper 继承自 Context ,ContextWrapper 内部包含 Context 类型的 mBase 对象,mBase 具体指向 ContextImpl。
ContextImpl 提供了很多功能,因此设计上使用了装饰模式, ContextWrapper 是装饰类, 它对 ContentImpl 进行包装, ContextWrapper 主要是起了方法传递的作用, ContextWrapper 中几乎所有的方法都是调用 ContextImpl 的相应方法来实现的。
ContextThemeWrapper、Service 和 Application 都继承自 ContextWrapper, 这样他们都可以通过 mBase 来使用 Context 的方法,同时它们也是装饰类,在ContextWrapper 的基础上又添加了不同的功能。
ContextThemeWrapper 中包含和主题相关的方法(比如 getTheme 方法),因此,需要主题的 Activity 继承 ContextThemeWrapper,而不需要主题的 Service 继承 ContextWrapper。
Context 的关联类采用了装饰模式:
- 使用者(比如 Servcice) 能够方便地使用 Context。
- 如果ContextImpl 发生了变化,它的装饰类 ContextWrapper 不需要做任何修改。
- ContextImpl 的实现不会暴露给使用者,使用者也不必关心 ContextImpl 的实现。
- 通过组合而非继承的方式,拓展 ContextImpl 的功能,在运行时选择不同的装饰类,实现不同的功能。
5.2 Application Context 的创建过程
通过getApplicationContext 来获取应用程序全局的 Application Context.
在一个应用程序启动完成后,应用程序就会有一个全局的 Application Context 。
Application Context 的创建过程:
// frameworks/base/core/java/android/app/ActivityThread.java
1074 private class ApplicationThread extends IApplicationThread.Stub {
1075 private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
1076
1077 public final void scheduleReceiver(Intent intent, ActivityInfo info,
1078 CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
1079 boolean sync, int sendingUser, int processState) {
1080 updateProcessState(processState, false);
1081 ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
1082 sync, false, mAppThread.asBinder(), sendingUser);
1083 r.info = info;
1084 r.compatInfo = compatInfo;
1085 sendMessage(H.RECEIVER, r); // 向 H类 发送消息
1086 }
class H extends Handler {
public static final int RECEIVER = 113;
}
public void handleMessage(Message msg) {
2187 if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
2188 switch (msg.what) {
...
case RECEIVER:
2202 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
2203 handleReceiver((ReceiverData)msg.obj); // 主要是该方法
2204 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
2205 break;
H 继承自 Handler ,是 ActivityThread 的内部类。
这里对比原书,android 12 的流程还是发生了一些变化
// frameworks/base/core/java/android/app/ActivityThread.java
4448 private void handleReceiver(ReceiverData data) {
4449 // If we are getting ready to gc after going to the background, well
4450 // we are back active so skip it.
4451 unscheduleGcIdler();
4452
4453 String component = data.intent.getComponent().getClassName();
4454 // apk 包的信息: 主要获取 packageInfo
4455 LoadedApk packageInfo = getPackageInfoNoCheck(
4456 data.info.applicationInfo, data.compatInfo);
4457
4458 IActivityManager mgr = ActivityManager.getService();
4459
4460 Application app;
4461 BroadcastReceiver receiver;
4462 ContextImpl context;
4463 try {
// 这里调用 makeApplication
4464 app = packageInfo.makeApplication(false, mInstrumentation); // 注释 1
4465 context = (ContextImpl) app.getBaseContext();
4466 if (data.info.splitName != null) {
4467 context = (ContextImpl) context.createContextForSplit(data.info.splitName);
4468 }
4469 if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
4470 final String attributionTag = data.info.attributionTags[0];
4471 context = (ContextImpl) context.createAttributionContext(attributionTag);
4472 }
4473 java.lang.ClassLoader cl = context.getClassLoader();
4474 data.intent.setExtrasClassLoader(cl);
4475 data.intent.prepareToEnterProcess(
4476 isProtectedComponent(data.info) || isProtectedBroadcast(data.intent),
4477 context.getAttributionSource());
4478 data.setExtrasClassLoader(cl);
4479 receiver = packageInfo.getAppFactory()
4480 .instantiateReceiver(cl, data.info.name, data.intent);
4481 } catch (Exception e) {
4482 if (DEBUG_BROADCAST) Slog.i(TAG,
4483 "Finishing failed broadcast to " + data.intent.getComponent());
4484 data.sendFinished(mgr);
4485 throw new RuntimeException(
4486 "Unable to instantiate receiver " + component
4487 + ": " + e.toString(), e);
4488 }
4489
4490 try {
4491 if (localLOGV) Slog.v(
4492 TAG, "Performing receive of " + data.intent
4493 + ": app=" + app
4494 + ", appName=" + app.getPackageName()
4495 + ", pkg=" + packageInfo.getPackageName()
4496 + ", comp=" + data.intent.getComponent().toShortString()
4497 + ", dir=" + packageInfo.getAppDir());
4498
4499 sCurrentBroadcastIntent.set(data.intent);
4500 receiver.setPendingResult(data);
4501
4502 //zte add for systrace tag
4503 if (ZtePerformanceDebug.DEBUG_SYSTRACE_TAG
4504 && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
4505 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
4506 "receiver:" + receiver + ", intent=" + data.intent);
4507 }
4508 //zte add end
4509 receiver.onReceive(context.getReceiverRestrictedContext(),
4510 data.intent);
4511 } catch (Exception e) {
4512 if (DEBUG_BROADCAST) Slog.i(TAG,
4513 "Finishing failed broadcast to " + data.intent.getComponent());
4514 data.sendFinished(mgr);
4515 if (!mInstrumentation.onException(receiver, e)) {
4516 throw new RuntimeException(
4517 "Unable to start receiver " + component
4518 + ": " + e.toString(), e);
4519 }
4520 } finally {
4521 sCurrentBroadcastIntent.set(null);
4522 }
4523
4524 if (receiver.getPendingResult() != null) {
4525 data.finish();
4526 }
4527
4528 //zte add for systrace tag
4529 if (ZtePerformanceDebug.DEBUG_SYSTRACE_TAG
4530 && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
4531 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
4532 }
4533 //zte add end
4534 }
注释1中,调用 LoadedApk 中的 makeApplication 方法:
注释1中,调用 LoadedApk 中的 makeApplication 方法:
// frameworks/base/core/java/android/app/LoadedApk.java
1316 public Application makeApplication(boolean forceDefaultAppClass,
1317 Instrumentation instrumentation) {
1318 if (mApplication != null) { // 1
1319 return mApplication;
1320 }
1321
1322 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
1323
1324 Application app = null;
1325
1326 String appClass = mApplicationInfo.className;
1327 if (forceDefaultAppClass || (appClass == null)) {
1328 appClass = "android.app.Application";
1329 }
1330
1331 try {
1332 final java.lang.ClassLoader cl = getClassLoader();
1333 if (!mPackageName.equals("android")) {
1334 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
1335 "initializeJavaContextClassLoader");
1336 initializeJavaContextClassLoader();
1337 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1338 }
1339
1340 // Rewrite the R 'constants' for all library apks.
1341 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(
1342 false, false);
1343 for (int i = 0, n = packageIdentifiers.size(); i < n; i++) {
1344 final int id = packageIdentifiers.keyAt(i);
1345 if (id == 0x01 || id == 0x7f) {
1346 continue;
1347 }
1348
1349 rewriteRValues(cl, packageIdentifiers.valueAt(i), id);
1350 }
1351
// 通过 ContextImpl 的 createAppContext 方法来创建 ContextImpl
1352 ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); //2
1353 // The network security config needs to be aware of multiple
1354 // applications in the same process to handle discrepancies
1355 NetworkSecurityConfigProvider.handleNewApplication(appContext);
// 创建 Application ,在 Instrumentation 的 newApplication 方法中传入了 ClassLoader 类型的对象以 及 注释2 处创建的ContextImpl
1356 app = mActivityThread.mInstrumentation.newApplication(
1357 cl, appClass, appContext); // 3
// 这里将 Application 赋值给 ContextImpl的 Context 类型的成员变量 mOuterContext, 这样 ContextImpl 中也包含了 Application 的引用。
1358 appContext.setOuterContext(app); // 4
1359 } catch (Exception e) {
1360 if (!mActivityThread.mInstrumentation.onException(app, e)) {
1361 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1362 throw new RuntimeException(
1363 "Unable to instantiate application " + appClass
1364 + " package " + mPackageName + ": " + e.toString(), e);
1365 }
1366 }
1367 mActivityThread.mAllApplications.add(app);
// 这里将 Application 赋值给 LoadedApk 的成员变量 mApplication -> 是Application类型的对象,用来代表 Application Context
1368 mApplication = app; // 5
1369
1370 if (instrumentation != null) {
1371 try {
1372 instrumentation.callApplicationOnCreate(app);
1373 } catch (Exception e) {
1374 if (!instrumentation.onException(app, e)) {
1375 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1376 throw new RuntimeException(
1377 "Unable to create application " + app.getClass().getName()
1378 + ": " + e.toString(), e);
1379 }
1380 }
1381 }
1382
1383 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1384
1385 return app;
1386 }
这里我们看看注释 3 处的 Application 是如何创建的, Instrumentation 的 newApplication 方法:
// frameworks/base/core/java/android/app/Instrumentation.java
1163 /**
1164 * Perform instantiation of the process's {@link Application} object. The
1165 * default implementation provides the normal system behavior.
1166 *
1167 * @param cl The ClassLoader with which to instantiate the object.
1168 * @param className The name of the class implementing the Application
1169 * object.
1170 * @param context The context to initialize the application with
1171 *
1172 * @return The newly instantiated Application object.
1173 */
1174 public Application newApplication(ClassLoader cl, String className, Context context)
1175 throws InstantiationException, IllegalAccessException,
1176 ClassNotFoundException {
1177 Application app = getFactory(context.getPackageName())
1178 .instantiateApplication(cl, className);
1179 app.attach(context);
1180 return app;
1181 }
1183 /**
1184 * Perform instantiation of the process's {@link Application} object. The
1185 * default implementation provides the normal system behavior.
1186 *
1187 * @param clazz The class used to create an Application object from.
1188 * @param context The context to initialize the application with
1189 *
1190 * @return The newly instantiated Application object.
1191 */
1192 static public Application newApplication(Class<?> clazz, Context context)
1193 throws InstantiationException, IllegalAccessException,
1194 ClassNotFoundException {
1195 Application app = (Application)clazz.newInstance();
1196 app.attach(context); // 1
1197 return app;
1198 }
Instrumentataion 中有两个 newApplication 重载方法,最终会调用上面这个方法。
注释1 处通过 反射来创建 Application ,并调用了 Application 的 attach 方法,将 ContextImpl 传进去,最后返回该 Application 的attach方法如下所示:
// frameworks/base/core/java/android/app/Application.java
329 @UnsupportedAppUsage
330 /* package */ final void attach(Context context) {
331 attachBaseContext(context);
332 mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
333 }
在attach 方法中调用了attachBaseContext 方法,他在 Application 的父类 ContextWrapper 中实现。
// frameworks/base/core/java/android/content/ContextWrapper.java
72 /**
73 * Set the base context for this ContextWrapper. All calls will then be
74 * delegated to the base context. Throws
75 * IllegalStateException if a base context has already been set.
76 *
77 * @param base The new base context for this wrapper.
78 */
79 protected void attachBaseContext(Context base) {
80 if (mBase != null) {
81 throw new IllegalStateException("Base context already set");
82 }
83 mBase = base;
84 }
这个base 一路传递过来指的是 ContextImpl, 它是 Context 的实现类,将ContextImpl 赋值给 ContextWrapper 的 Context 类型的成员变量 mBase , 这样在 ContextWrapper 中就可以使用Context 的方法。
Application 的 attach 方法的作用就是使 Application 可以 Context 的方法,这样 Application 才可以用来代表 Application Context。
总结
android 12 的流程有变,但是很多地方并没有该,梳理流程如下:
[ActivityThread.java]
| scheduleReceiver()
| | sendMessage(H.RECEIVER, r)
| |
| H
| | handleMessage(Message msg)
| | handleReceiver((ReceiverData)msg.obj)
| | | app = packageInfo.makeApplication(false, mInstrumentation);
| | | |
| | | [LoadApk.java]
| | | | makeApplication
| | | | |
| | | | [Instrumentation.java]
| | | | | newApplication
| | | | | | app.attach(context)
| | | | | | |
| | | | | | [Application.java]
| | | | | | | attachBaseContext(context)
| | | | | | | |
| | | | | | | ContextWrapper
5.3 Application Context 的获取过程
上面我们知道了 Application Context 的创建,现在我们来看看它的获取。
这里主要通过调用 getApplicationContext 方法来获得 Application Context,该方法在 ContextWrapperer 中实现。
// frameworks/base/core/java/android/content/ContextWrapper.java
124 public Context getApplicationContext() {
125 return mBase.getApplicationContext();
126 }
127
这里 mBase 指的是 ContextImpl, 看看 ContextImpl 的 getApplicationContext 方法:
// frameworks/base/core/java/android/app/ContextImpl.java
407 public Context getApplicationContext() {
408 return (mPackageInfo != null) ?
409 mPackageInfo.getApplication() : mMainThread.getApplication();
410 }
如果LoadedApk 类型的mPackageInfo 不为 null, 则调用 LoadedApk 的 getApplication 方法,否则调用 ActivityThread 的 getApplication 方法。由于应用程序已经启动,LoadedApk不会为 null ,则会调用 LoadApk 的 getApplication 方法。
// frameworks/base/core/java/android/app/LoadedApk.java
162 Application getApplication() {
163 return mApplication;
164 }
这里的 mApplication 在上文 LoadedApk 的 makeApplication 方法的注释5 处被赋值。
这样我们通过 getApplicationContext 方法就获取到了 Application Context.
5.4 Activity 的 Context 创建过程
想要在 Activity 中使用 Context 提供的方法,务必要先创建 Context。
Activity 的 Context 会在 Activity 的启动过程中被创建。
我们直接看看 ActivityThread 的 performLaunchActivity 方法:
// frameworks/base/core/java/android/app/ActivityThread.java
/** Core implementation of activity launch. */
3683 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
3684 ActivityInfo aInfo = r.activityInfo;
3685 if (r.packageInfo == null) {
3686 r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
3687 Context.CONTEXT_INCLUDE_CODE);
3688 }
3689
3690 if (ZTE_TRAVERSAL_ACCELERATE_ENABLED) {
3691 // nubia add for app launch traversals accelerate
3692 if (sIsAppFirstStartActivity) {
3693 sIsAppFirstStartActivity = false;
3694 if (r != null && r.intent != null) {
3695 String intentInfoStr = r.intent.toString();
3696 if (!(intentInfoStr != null && intentInfoStr.contains(Intent.ACTION_MAIN)
3697 && intentInfoStr.contains(Intent.CATEGORY_LAUNCHER))) {
3698 //if app not launch from Launcher so disable app launch traversals accelerate.
3699 sIsEnableAppTraversalsAccelerate = false;
3700 }
3701 }
3702 if (sIsEnableAppTraversalsAccelerate) {
3703 mH.removeCallbacks(mDisableAppTraversalsAccelerateRunnable);
3704 mH.postDelayed(mDisableAppTraversalsAccelerateRunnable, 3000);
3705 }
3706 }
3707 // nubia add end
3708 }
3709 ComponentName component = r.intent.getComponent();
3710 if (component == null) {
3711 component = r.intent.resolveActivity(
3712 mInitialApplication.getPackageManager());
3713 r.intent.setComponent(component);
3714 }
3715
3716 if (r.activityInfo.targetActivity != null) {
3717 component = new ComponentName(r.activityInfo.packageName,
3718 r.activityInfo.targetActivity);
3719 }
3720 // 通过createBaseContextForActivity 方法来创建 Activity 的 ContextImpl
// 并将其传入注释4处的 activity 的 attach 方法中
// 这样ContextImpl 也可以访问 Activity 的变量和方法
// createBaseContextForActivity 中会调用ContextImpl 的 createActivityContext 方法来创建 ContextImpl
3721 ContextImpl appContext = createBaseContextForActivity(r); // 1
3722 Activity activity = null;
3723 try {
3724 java.lang.ClassLoader cl = appContext.getClassLoader();
// 这里来创建 Activity 的实例
3725 activity = mInstrumentation.newActivity(
3726 cl, component.getClassName(), r.intent); // 2
3727 StrictMode.incrementExpectedActivityCount(activity.getClass());
3728 r.intent.setExtrasClassLoader(cl);
3729 r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
3730 appContext.getAttributionSource());
3731 if (r.state != null) {
3732 r.state.setClassLoader(cl);
3733 }
3734 } catch (Exception e) {
3735 if (!mInstrumentation.onException(activity, e)) {
3736 throw new RuntimeException(
3737 "Unable to instantiate activity " + component
3738 + ": " + e.toString(), e);
3739 }
3740 }
3741
3742 try {
3743 Application app = r.packageInfo.makeApplication(false, mInstrumentation);
3744
3745 if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
3746 if (localLOGV) Slog.v(
3747 TAG, r + ": app=" + app
3748 + ", appName=" + app.getPackageName()
3749 + ", pkg=" + r.packageInfo.getPackageName()
3750 + ", comp=" + r.intent.getComponent().toShortString()
3751 + ", dir=" + r.packageInfo.getAppDir());
3752
3753 if (activity != null) {
3754 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
3755 Configuration config =
3756 new Configuration(mConfigurationController.getCompatConfiguration());
3757 if (r.overrideConfig != null) {
3758 config.updateFrom(r.overrideConfig);
3759 }
3760 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
3761 + r.activityInfo.name + " with config " + config);
3762 Window window = null;
3763 if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
3764 window = r.mPendingRemoveWindow;
3765 r.mPendingRemoveWindow = null;
3766 r.mPendingRemoveWindowManager = null;
3767 }
3768
3769 // Activity resources must be initialized with the same loaders as the
3770 // application context.
3771 appContext.getResources().addLoaders(
3772 app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
3773
3774 appContext.setOuterContext(activity); // 3
3775 activity.attach(appContext, this, getInstrumentation(), r.token,
3776 r.ident, app, r.intent, r.activityInfo, title, r.parent,
3777 r.embeddedID, r.lastNonConfigurationInstances, config,
3778 r.referrer, r.voiceInteractor, window, r.configCallback,
3779 r.assistToken, r.shareableActivityToken); // 4
3780
3781 if (customIntent != null) {
3782 activity.mIntent = customIntent;
3783 }
3784 r.lastNonConfigurationInstances = null;
3785 checkAndBlockForNetworkAccess();
3786 activity.mStartedActivity = false;
3787 int theme = r.activityInfo.getThemeResource();
3788 if (theme != 0) {
3789 activity.setTheme(theme);
3790 }
3791
3792 if (r.mActivityOptions != null) {
3793 activity.mPendingOptions = r.mActivityOptions;
3794 r.mActivityOptions = null;
3795 }
3796 activity.mLaunchedFromBubble = r.mLaunchedFromBubble;
3797 activity.mCalled = false;
3798 if (r.isPersistable()) {
//调用 Activity 的 onCreate 方法
3799 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); // 5
3800 } else {
3801 mInstrumentation.callActivityOnCreate(activity, r.state);
3802 }
3803 if (!activity.mCalled) {
3804 throw new SuperNotCalledException(
3805 "Activity " + r.intent.getComponent().toShortString() +
3806 " did not call through to super.onCreate()");
3807 }
3808 r.activity = activity;
3809 mLastReportedWindowingMode.put(activity.getActivityToken(),
3810 config.windowConfiguration.getWindowingMode());
3811 }
3812 r.setState(ON_CREATE);
3813
3814 // updatePendingActivityConfiguration() reads from mActivities to update
3815 // ActivityClientRecord which runs in a different thread. Protect modifications to
3816 // mActivities to avoid race.
3817 synchronized (mResourcesManager) {
3818 mActivities.put(r.token, r);
3819 }
3820
3821 } catch (SuperNotCalledException e) {
3822 throw e;
3823
3824 } catch (Exception e) {
3825 if (!mInstrumentation.onException(activity, e)) {
3826 throw new RuntimeException(
3827 "Unable to start activity " + component
3828 + ": " + e.toString(), e);
3829 }
3830 }
3831
3832 return activity;
3833 }
这里单独说一下注释4处的 Activity 的 attach 方法: 这里单独说一下注释4处的 Activity 的 attach 方法:
// frameworks/base/core/java/android/app/Activity.java
final void attach(Context context, ActivityThread aThread,
8532 Instrumentation instr, IBinder token, int ident,
8533 Application application, Intent intent, ActivityInfo info,
8534 CharSequence title, Activity parent, String id,
8535 NonConfigurationInstances lastNonConfigurationInstances,
8536 Configuration config, String referrer, IVoiceInteractor voiceInteractor,
8537 Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
8538 IBinder shareableActivityToken) {
8539 attachBaseContext(context); // 1
8540
8541 mFragments.attachHost(null /*parent*/);
8542 // 创建 PhoneWindow ,代表应用程序窗口
// PhoneWindow 在运行中会间接触发很多事件,比如点击、菜单弹出、屏幕焦点变化等事件
// 这些事件需要转发给与 PhoneWindow 关联的 Activity
// 转发操作通过Window.Callback 接口实现,Activity 实现了这个接口
8543 mWindow = new PhoneWindow(this, window, activityConfigCallback); // 2
8544 mWindow.setWindowControllerCallback(mWindowControllerCallback);
// 将当前Activity 通过 Window 的 setCallback 方法传递给 PhoneWindow
8545 mWindow.setCallback(this); // 3
8546 mWindow.setOnWindowDismissedCallback(this);
8547 mWindow.getLayoutInflater().setPrivateFactory(this);
8548 if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
8549 mWindow.setSoftInputMode(info.softInputMode);
8550 }
8551 if (info.uiOptions != 0) {
8552 mWindow.setUiOptions(info.uiOptions);
8553 }
8554 mUiThread = Thread.currentThread();
8555
8556 mMainThread = aThread;
8557 mInstrumentation = instr;
8558 mToken = token;
8559 mAssistToken = assistToken;
8560 mShareableActivityToken = shareableActivityToken;
8561 mIdent = ident;
8562 mApplication = application;
8563 mIntent = intent;
8564 mReferrer = referrer;
8565 mComponent = intent.getComponent();
8566 mActivityInfo = info;
8567 mTitle = title;
8568 mParent = parent;
8569 mEmbeddedID = id;
8570 mLastNonConfigurationInstances = lastNonConfigurationInstances;
8571 if (voiceInteractor != null) {
8572 if (lastNonConfigurationInstances != null) {
8573 mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
8574 } else {
8575 mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
8576 Looper.myLooper());
8577 }
8578 }
8579 // 给PhoneWindow 设置 WindowManager
8580 mWindow.setWindowManager(
8581 (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
8582 mToken, mComponent.flattenToString(),
8583 (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); // 4
8584 if (mParent != null) {
8585 mWindow.setContainer(mParent.getWindow());
8586 }
// 获取 WindowManager 并赋值给 Activity 的成员变量 mWindowManager
// 这样在 Activity 中就可以通过 getWindowManager 方法来获取 WindowManager
8587 mWindowManager = mWindow.getWindowManager(); // 5
8588 mCurrentConfig = config;
8589
8590 mWindow.setColorMode(info.colorMode);
8591 mWindow.setPreferMinimalPostProcessing(
8592 (info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);
8593
8594 setAutofillOptions(application.getAutofillOptions());
8595 setContentCaptureOptions(application.getContentCaptureOptions());
8596
8597 try {
8598 mClipboardManager = new ClipboardManager(context, null);
8599 } catch (Exception e) {
8600 Slog.w(TAG, "ClipboardManager get failed", e);
8601 }
8602
8603 }
注释1 处的 attachBaseContext 方法在 ContextThemeWrapper 中实现。
// frameworks/base/core/java/android/view/ContextThemeWrapper.java
86 protected void attachBaseContext(Context newBase) {
87 super.attachBaseContext(newBase);
88 }
attachBaseContext 方法接着调用 ContextThemeWrapper 的父类 ContextWrapper 的 attachBaseContext 方法:
// frameworks/base/core/java/android/content/ContextWrapper.java
79 protected void attachBaseContext(Context base) {
80 if (mBase != null) {
81 throw new IllegalStateException("Base context already set");
82 }
// 这里的 base 指的是一路传递过来的 Activity 的 ContextImpl
// 将它赋值给 ContextWrapper 的成员变量 mBase
// 这样 ContextWrapper 的功能就可以交由 ContextImpl 来处理
83 mBase = base;
84 }
当我们调用ContextWrapper 的 getTheme 方法时,其实就是调用了 ContextImpl 的 getTheme 方法。
// frameworks/base/core/java/android/content/ContextWrapper.java
141 public Resources.Theme getTheme() {
142 return mBase.getTheme();
143 }
144
总结
在启动Activity 的过程中创建 ContextImpl , 并赋值给 ContextWrapper 的成员变量mBase。
Activity 继承自 ContextWrapper 的子类 ContextThemeWrapper, 这样在 Activity 中就可以使用 Context 中定义的方法了。
5.5 Service 的 Context 创建过程
Service 的Context 创建过程与 Activity 的 Context 创建过程类似,是在Service 的启动过程中被创建的。
ActivityThread 启动 Service
ActivityThread 的内部类 ApplicationThread 会调用 scheduleCreateService 方法来启动 Service.
// frameworks/base/core/java/android/app/ActivityThread.java
1110 public final void scheduleCreateService(IBinder token,
1111 ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
1112 updateProcessState(processState, false);
1113 CreateServiceData s = new CreateServiceData();
1114 s.token = token;
1115 s.info = info;
1116 s.compatInfo = compatInfo;
1117 // sendMessage 方法向 H 类发送 CREATE_SERVICE 类型的消息
// H 类的 handleMessage 方法会对 CREATE_SERVICE 类型的消息进行处理
1118 sendMessage(H.CREATE_SERVICE, s);
1119 }
1120
这里整体的流程和 Activity 的 Context 创建类似:
// frameworks/base/core/java/android/app/ActivityThread.java
private void handleCreateService(CreateServiceData data) {
4658 // If we are getting ready to gc after going to the background, well
4659 // we are back active so skip it.
4660 unscheduleGcIdler();
4661
4662 LoadedApk packageInfo = getPackageInfoNoCheck(
4663 data.info.applicationInfo, data.compatInfo);
4664 Service service = null;
4665 try {
4666 if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
4667
4668 Application app = packageInfo.makeApplication(false, mInstrumentation); // 1
4669
4670 final java.lang.ClassLoader cl;
4671 if (data.info.splitName != null) {
4672 cl = packageInfo.getSplitClassLoader(data.info.splitName);
4673 } else {
4674 cl = packageInfo.getClassLoader();
4675 }
4676 service = packageInfo.getAppFactory()
4677 .instantiateService(cl, data.info.name, data.intent);
4678 ContextImpl context = ContextImpl.getImpl(service
4679 .createServiceBaseContext(this, packageInfo));
4680 if (data.info.splitName != null) {
4681 context = (ContextImpl) context.createContextForSplit(data.info.splitName);
4682 }
4683 if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
4684 final String attributionTag = data.info.attributionTags[0];
4685 context = (ContextImpl) context.createAttributionContext(attributionTag);
4686 }
4687 // Service resources must be initialized with the same loaders as the application
4688 // context.
4689 context.getResources().addLoaders(
4690 app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
4691
4692 context.setOuterContext(service);
4693 service.attach(context, this, data.info.name, data.token, app,
4694 ActivityManager.getService()); // 2
4695 //zte add for systrace tag
4696 if (ZtePerformanceDebug.DEBUG_SYSTRACE_TAG
4697 && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
4698 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "onCreate:" + service);
4699 }
4700 //zte add end
4701 service.onCreate();
4702 mServicesData.put(data.token, data);
4703 if (ZtePerformanceDebug.DEBUG_SYSTRACE_TAG
4704 && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
4705 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
4706 }
4707 //zte add end
4708 mServices.put(data.token, service);
4709 try {
4710 ActivityManager.getService().serviceDoneExecuting(
4711 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
4712 } catch (RemoteException e) {
4713 throw e.rethrowFromSystemServer();
4714 }
4715 } catch (Exception e) {
4716 if (!mInstrumentation.onException(service, e)) {
4717 throw new RuntimeException(
4718 "Unable to create service " + data.info.name
4719 + ": " + e.toString(), e);
4720 }
4721 }
4722 }
4723
学习分享
在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了
很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘
如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。
2021最新上万页的大厂面试真题
七大模块学习资料:如NDK模块开发、Android框架体系架构…
只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。
这份体系学习笔记,适应人群:
**第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。
**第二,**开发几年,不知道如何进阶更进一步,比较迷茫。
第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!
由于文章内容比较多,篇幅不允许,部分未展示内容以截图方式展示 。如有需要获取完整的资料文档的朋友扫描下方二维码免费获取。
今天的文章android的context的作用_android怎么注释代码分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/89469.html