IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 《Andorid 进阶解密》—— 理解上下文 Context -> 正文阅读

[移动开发]《Andorid 进阶解密》—— 理解上下文 Context

5.1 理解上下文

Context 也就是上下文对象,是 Android 常用的类。

Context 意为上下文,是一个应用程序环境信息的接口。

使用场景:

1. 使用 Context 调用方法,比如启动 Activity、访问资源、调用系统级服务等。
2. 调用方法时传入 Context, 比如弹出 Toast、 创建 Dialog 等。

Activity 、 Service 和 Application 都间接地继承自 Context 。

一个应用程序进程中有多少个 Context ,这个数量等于 Activity 和 Service 的总个数加 1,1指的是 Application 的数量。

Context 是一个抽象类,它的内部定义了很多方法以及静态常量,它的具体实现为 ContextImpl。

和Cotext 相关联的类, 除了 ContextImpl ,还有 ContextWrapper、ContextThemeWrapper 和 Activity 等。

epub_31186331_291

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 的关联类采用了装饰模式:

  1. 使用者(比如 Servcice) 能够方便地使用 Context。
  2. 如果ContextImpl 发生了变化,它的装饰类 ContextWrapper 不需要做任何修改。
  3. ContextImpl 的实现不会暴露给使用者,使用者也不必关心 ContextImpl 的实现。
  4. 通过组合而非继承的方式,拓展 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 方法:

// 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 方法:

// 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  

Y_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


  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-06 13:12:56  更:2022-03-06 13:15:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 16:36:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码