Activity的启动流程

小伙伴们面试的时候是不是被问过Activity的启动流程很多啊。那我们就来看看吧。个人感觉这类文章代码细节太多,反而容易迷失在源码调用之中,从而忽略了Activity启动过程的本质。所以本文就简单地定性地对Activity启动过程进行描述,不会贴上大篇幅的源码。本文是根据Android11.0系统源码讲述的。

冷启动与热启动

Activity启动过程中,一般会牵涉到应用启动的流程。应用启动又分为冷启动和热启动。

  1. 冷启动:点击桌面图标,手机系统不存在该应用进程,这时系统会重新fork一个子进程来加载Application并启动Activity,这个启动方式就是冷启动。
  2. 热启动:应用的热启动比冷启动简单得多,开销也更低。在热启动中,因为系统里已有该应用的进程,所以系统的所有工作就是将您的 Activity 带到前台。 冷启动是应用完全从0开始启动,涉及到更多的内容,所以就应用冷启动的过程展开讨论。

应用启动流程

一般来说,冷启动包括了以下内容:

  1. 启动进程 点击图标发生在Launcher应用的进程,startActivity()函数最终调用的是Instrumentation中execStartActivity

/frameworks/base/core/java/android/app/Activity.java

startActivity

调用的是startActivityForResult 

 startActivityForResult

调用的是Instrumentation 里面的  

 /frameworks/base/core/java/android/app/Instrumentation.java

这个圈起来的地方android9.0以及9.0以前是这样调用的,直接调用的是AMS的startActivity

9.0之后是这样调用的,调用的是ATM的startActivity

ActivityTaskManager.getService 是获取的什么呢

  public static IActivityManager getService() {
4126          return IActivityManagerSingleton.get();
4127      }
4128  
4129      private static final Singleton<IActivityManager> IActivityManagerSingleton =
4130              new Singleton<IActivityManager>() {
4131                  @Override
4132                  protected IActivityManager create() {
4133                      final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
4134                      final IActivityManager am = IActivityManager.Stub.asInterface(b);
4135                      return am;
4136                  }
4137              };
4138  

 获取的是IActivityManager,通过跨进程进入到ActivityManagerService中的startActivity

/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

 @Override
1210      public final int startActivity(IApplicationThread caller, String callingPackage,
1211              String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
1212              String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
1213              Bundle bOptions) {
1214          return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
1215                  resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
1216                  UserHandle.getCallingUserId());
1217      }
    private int startActivityAsUser(IApplicationThread caller, String callingPackage,
1245              @Nullable String callingFeatureId, Intent intent, String resolvedType,
1246              IBinder resultTo, String resultWho, int requestCode, int startFlags,
1247              ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
1248  
1249          final SafeActivityOptions opts = SafeActivityOptions.fromBundle(bOptions);
1250  
1251          assertPackageMatchesCallingUid(callingPackage);
1252          enforceNotIsolatedCaller("startActivityAsUser");
1253  
1254          if (intent != null && intent.isSandboxActivity(mContext)) {
1255              SdkSandboxManagerLocal sdkSandboxManagerLocal = LocalManagerRegistry.getManager(
1256                      SdkSandboxManagerLocal.class);
1257              sdkSandboxManagerLocal.enforceAllowedToHostSandboxedActivity(
1258                      intent, Binder.getCallingUid(), callingPackage
1259              );
1260          }
1261  
1262          if (Process.isSdkSandboxUid(Binder.getCallingUid())) {
1263              SdkSandboxManagerLocal sdkSandboxManagerLocal = LocalManagerRegistry.getManager(
1264                      SdkSandboxManagerLocal.class);
1265              if (sdkSandboxManagerLocal == null) {
1266                  throw new IllegalStateException("SdkSandboxManagerLocal not found when starting"
1267                          + " an activity from an SDK sandbox uid.");
1268              }
1269              sdkSandboxManagerLocal.enforceAllowedToStartActivity(intent);
1270          }
1271  
1272          userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
1273                  Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
1274  
1275          // TODO: Switch to user app stacks here.
1276          return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
1277                  .setCaller(caller)
1278                  .setCallingPackage(callingPackage)
1279                  .setCallingFeatureId(callingFeatureId)
1280                  .setResolvedType(resolvedType)
1281                  .setResultTo(resultTo)
1282                  .setResultWho(resultWho)
1283                  .setRequestCode(requestCode)
1284                  .setStartFlags(startFlags)
1285                  .setProfilerInfo(profilerInfo)
1286                  .setActivityOptions(opts)
1287                  .setUserId(userId)
1288                  .execute();
1289  
1290      }

跳转到/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

执行execute

 然后看executeRequest 中代码

 再看startActivityUnchecked

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1459              IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1460              int startFlags, ActivityOptions options, Task inTask,
1461              TaskFragment inTaskFragment, @BalCode int balCode,
1462              NeededUriGrants intentGrants, int realCallingUid) {
1463          int result = START_CANCELED;
1464          final Task startedActivityRootTask;
1465  
1466          // Create a transition now to record the original intent of actions taken within
1467          // startActivityInner. Otherwise, logic in startActivityInner could start a different
1468          // transition based on a sub-action.
1469          // Only do the create here (and defer requestStart) since startActivityInner might abort.
1470          final TransitionController transitionController = r.mTransitionController;
1471          Transition newTransition = transitionController.isShellTransitionsEnabled()
1472                  ? transitionController.createAndStartCollecting(TRANSIT_OPEN) : null;
1473          RemoteTransition remoteTransition = r.takeRemoteTransition();
1474          try {
1475              mService.deferWindowLayout();
1476              transitionController.collect(r);
1477              try {
1478                  Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
1479                  result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
1480                          startFlags, options, inTask, inTaskFragment, balCode,
1481                          intentGrants, realCallingUid);
1482              } finally {
1483                  Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
1484                  startedActivityRootTask = handleStartResult(r, options, result, newTransition,
1485                          remoteTransition);
1486              }
1487          } finally {
1488              mService.continueWindowLayout();
1489          }
1490          postStartActivityProcessing(r, result, startedActivityRootTask);
1491  
1492          return result;
1493      }

继续看startActivityInner,如图红色框标志的代码

跳转到 frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

看resumeFocusedTasksTopActivities

resumeTopActivityUnCheckedLocked 

接着到  /frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java 中resumeTopActivityUnCheckedLocked ,调用红色边框线内代码

 

resumeTopActivityInnerLocked 

 /frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

判断如果进程存在,执行realStartActivityLocked;进程不存在,执行mService.startProcessAsync。这样就回到了开头我们说的冷启动,就会发送请求给Zygote进程,fork出新进程。

/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

 跳转到ActivityManagerService中的startProcess

 然后接着看startProcessLocked

跳转到 /frameworks/base/services/core/java/com/android/server/am/ProcessList.java

中startProcessLocked,执行如下代码

 startProcess中执行的是Process start

ZYGOT_PROCESS start 调用的是

/frameworks/base/core/java/android/os/ZygoteProcess.java 里的start

startViaZygote: 

看第一个参数openZygoteSocketIfNeeded, 

调用的attemptConnectionToPrimaryZygote

connect: 

创建了Socket,然后连接zygote

 

回过头来看startViaZygote这个方法,最后返回的是

 然后调用attemptUsapSendArgsAndGetResult

usapWriter.write 写数据,usapReader.read读数据,完成AMS和Zygote之间的通讯。

Zygote是如何创建进程的呢,其实是和system_server创建进程一样的,最终执行的是ActivityThread中的main方法

/frameworks/base/core/java/android/app/ActivityThread.java

 public static void main(String[] args) {
7612          Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
7613  
7614          // Install selective syscall interception
7615          AndroidOs.install();
7616  
7617          // CloseGuard defaults to true and can be quite spammy.  We
7618          // disable it here, but selectively enable it later (via
7619          // StrictMode) on debug builds, but using DropBox, not logs.
7620          CloseGuard.setEnabled(false);
7621  
7622          Environment.initForCurrentUser();
7623  
7624          // Make sure TrustedCertificateStore looks in the right place for CA certificates
7625          final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
7626          TrustedCertificateStore.setDefaultUserDirectory(configDir);
7627  
7628          // Call per-process mainline module initialization.
7629          initializeMainlineModules();
7630  
7631          Process.setArgV0("<pre-initialized>");
7632  
7633          Looper.prepareMainLooper();
7634  
7635          // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
7636          // It will be in the format "seq=114"
7637          long startSeq = 0;
7638          if (args != null) {
7639              for (int i = args.length - 1; i >= 0; --i) {
7640                  if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
7641                      startSeq = Long.parseLong(
7642                              args[i].substring(PROC_START_SEQ_IDENT.length()));
7643                  }
7644              }
7645          }
7646          ActivityThread thread = new ActivityThread();
7647          thread.attach(false, startSeq);
7648  
7649          if (sMainThreadHandler == null) {
7650              sMainThreadHandler = thread.getHandler();
7651          }
7652  
7653          if (false) {
7654              Looper.myLooper().setMessageLogging(new
7655                      LogPrinter(Log.DEBUG, "ActivityThread"));
7656          }
7657  
7658          // End of event ActivityThreadMain.
7659          Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
7660          Looper.loop();
7661  
7662          throw new RuntimeException("Main thread loop unexpectedly exited");
7663      }
7664  

AMS是通过thread.attah管理新进程中的Activity的

 

其中  final IActivityManager mgr = ActivityManager.getService(); 获取到AMS,然后mgr.attachApplication 添加 ApplicationThread

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/451052.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Ettus USRP X440对雷达和EW系统进行原型验证

概览 无论是保障己方平台的生存能力&#xff0c;还是扰乱敌方频谱使用&#xff0c;以电磁(EM)频谱为主导都是任务成功的主要因素。电磁频谱操作(Electromagnetic Spectrum Operation, EMSO)需要使用战术系统来监测敌方的频谱活动、定位其发射器并帮助己方制定行动计划。软件无…

断电保持霍尔传感器

断电保持霍尔传感器的工作原理 断电保持霍尔传感器是一种利用变压器或共振电路的检测元件&#xff0c;通过检测物体与探头之间的物理距离控制电路的开关状态&#xff0c;从而实现对物体位置和状态的监测。该开关可以通过调试和校准以满足不同场合的要求。 断电保持霍尔传感器控…

19.HarmonyOS App(JAVA)依赖布局DependentLayout使用方法

layout/ability_main.xml 显示位置不对&#xff1a;检查布局文件ohos:lef_of "id:tuzi",比如显示在兔子的左侧&#xff0c;这里就会显示不对。 需要id前没有$符号。改为&#xff1a; ohos:lef_of "$id:tuzi" <?xml version"1.0" encodi…

蓝桥杯嵌入式第七届真题(完成) STM32G431

蓝桥杯嵌入式第七届真题(完成) STM32G431 题目 相关文件 main.c /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief : Main program body**********************…

简单说说redis分布式锁

什么是分布式锁 分布式锁&#xff08;多服务共享锁&#xff09;在分布式的部署环境下&#xff0c;通过锁机制来让多客户端互斥的对共享资源进行访问/操作。 为什么需要分布式锁 在单体应用服务里&#xff0c;不同的客户端操作同一个资源&#xff0c;我们可以通过操作系统提供…

整理:汉诺塔简析

大体上&#xff0c;要解决一个汉诺塔问题&#xff0c;就需要解决两个更简单的汉诺塔问题 以盘子数量 3 的汉诺塔问题为例 要将 3 个盘子从 A 移动到 C&#xff0c;就要&#xff1a; 将两个盘子从 A 移动到 B&#xff08;子问题 1&#xff09; 为了解决子问题 1&#xff0c;就…

[晓理紫]CCF系列会议截稿时间订阅

关注{晓理紫|小李子}&#xff0c;每日更新CCF系列会议信息&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持&#xff01;&#xff01; 如果你感觉对你有所帮助&#xff0c;请关注我&#xff0c;每日准时为你推送最新会议信息。 SAC (CCF C) Select…

WordPress每天发布60s插件

源码名称:WordPress每天发布60s插件 适用平台:WordPress Wordpress还是比较适合个人博客网站&#xff0c;这个60秒插件适合一些喜欢自动发新闻早报晚报人员 喜欢的赶紧下手。找 万能工具箱合集 小程序即可找到资源

如何结合ChatGPT生成个人魔法咒语词库

3.6.1 ChatGPT辅助力AI绘画 3.6.1.1 给定主题让ChatGPT直接描述 上面给了一个简易主题演示一下&#xff0c;这是完全我没有细化的提问&#xff0c;然后把直接把这些关键词组合在一起。 关键词&#xff1a; 黄山的美景&#xff0c;生机勃勃&#xff0c;湛蓝天空&#xff0c;青…

回归预测 | Matlab实现POA-CNN-LSTM-Attention鹈鹕算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)

回归预测 | Matlab实现POA-CNN-LSTM-Attention鹈鹕算法优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&#xff09; 目录 回归预测 | Matlab实现POA-CNN-LSTM-Attention鹈鹕算法优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&…

林浩然的教育营销课:培养人才的“秘密配方”

林浩然的教育营销课&#xff1a;培养人才的“秘密配方” Lin Haoran’s Education Marketing Course: The “Secret Recipe” for Talent Development 在教育的烹饪界&#xff0c;林浩然老师就像是那位明星主厨&#xff0c;他的课堂总是座无虚席&#xff0c;学生们争相报名&…

[C++]:15.继承

继承 一.继承&#xff1a;1.继承的概念和基本操作&#xff1a;1.概念&#xff1a;2.基本操作&#xff1a; 2.继承格式和多种继承方法&#xff1a;1.基本继承格式&#xff1a;2.继承关系访问限定符 3.子类对象和父类对象之间的赋值&#xff1a;1.为什么存在赋值兼容转换&#xf…