尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Android14应用冷启动源码2,从 Zygote fork 到 onCreate:Activity 启动流程六阶段拆解
继续上一篇 Android14 应用冷启动源码从 ActivityThread.attach 到 AttachApplicationHelper-CSDN博客 这一篇继续追踪剩余的应用启动流程。现在已经看到ActivityStackSupervisor的realStartActivityLocked方法了。看下代码太庞大重点是这一段final LaunchActivityItem launchActivityItem LaunchActivityItem.obtain(r.token, r.intent, System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), deviceId, r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, r.takeOptions(), isTransitionForward, proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController, r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken); // Set desired final state. final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem ResumeActivityItem.obtain(r.token, isTransitionForward, r.shouldSendCompatFakeFocus()); } else { lifecycleItem PauseActivityItem.obtain(r.token); } // Schedule transaction. mService.getLifecycleManager().scheduleTransactionAndLifecycleItems( proc.getThread(), launchActivityItem, lifecycleItem);LaunchActivityItem.obtain(...) 这里把启动 Activity 所需的数据——r.token目标标识、r.intent、r.infoActivityInfo、配置、保存的状态、结果、新 Intent、profiler 信息等——打包成一个命令对象。andResume true启动完这个 Activity 之后紧接着要走 Resume让它可见、获得焦点所以搭配 ResumeActivityItem。 栈顶activity启动走这个分支。 而andResume为false时只创建不需要立刻 onResume。最后一段代码scheduleTransactionAndLifecycleItems第一个参数是ApplicationThread 代理。继续追踪下这里mService就是ActivityTaskManagerService对象getLifecycleManager代码在这里看下ClientLifecycleManager的scheduleTransactionAndLifecycleItems方法代码/** * Schedules a single transaction item with a lifecycle request, delivery to client application. * throws RemoteException * see ClientTransactionItem */ void scheduleTransactionAndLifecycleItems(NonNull IApplicationThread client, NonNull ClientTransactionItem transactionItem, NonNull ActivityLifecycleItem lifecycleItem) throws RemoteException { // The behavior is different depending on the flag. // When flag is on, we wait until RootWindowContainer#performSurfacePlacementNoTrace to // dispatch all pending transactions at once. if (Flags.bundleClientTransactionFlag()) { final ClientTransaction clientTransaction getOrCreatePendingTransaction(client); clientTransaction.addTransactionItem(transactionItem); clientTransaction.addTransactionItem(lifecycleItem); onClientTransactionItemScheduledLocked(clientTransaction); } else { // TODO(b/260873529): cleanup after launch. final ClientTransaction clientTransaction ClientTransaction.obtain(client); clientTransaction.addCallback(transactionItem); clientTransaction.setLifecycleStateRequest(lifecycleItem); scheduleTransaction(clientTransaction); } }它有两个分支由 Flags.bundleClientTransactionFlag() 控制flag 关闭旧路径立即组装 ClientTransaction 并发出。flag 开启新路径先不发出把事务项攒进一个 pending 事务里等 RootWindowContainer#performSurfacePlacementNoTrace 时统一 dispatch。注释写得很直白we wait until ... to dispatch all pending transactions at once。这是新版的性能优化把多次 Binder 调用合并成一次减少 IPC 次数。ClientTransaction.obtain(client)创建事务client 就是 proc.getThread()即 ApplicationThread 代理。事务知道“发给谁”。addCallback(transactionItem)挂上 LaunchActivityItem即“启动指令”。setLifecycleStateRequest(lifecycleItem)挂上 ResumeActivityItem 或 PauseActivityItem即“目标生命周期”。scheduleTransaction(clientTransaction)这里才是真正发出。代码如下继续追踪调用了ClientTransaction的schedule方法mClient.scheduleTransaction(this); 这一行就是 SystemServer 侧发出 Binder 调用的最后一环。mClient 是 IApplicationThread 代理scheduleTransaction(this) 就是把整个 ClientTransaction 打包通过 Binder 发到 App 进程。到这里SystemServer 侧的“组装 → 发出”就闭环了。调用到ApplicationThread的scheduleTransaction方法这里ActivityThread里面没定义scheduleTransaction方法在它的父类ClientTransactionHandler里sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); 切换到主线程看下这个执行事务的消息重点看mTransactionExecutor.execute(transaction); 执行事务。看TransactionExecutor的execute方法如下重点看executeTransactionItems(transaction); 方法如下记得第一个事务是LaunchActivityItem应该是走else分支执行executeNonLifecycleItem。另一个事务是生命周期的后面再来看。先看executeNonLifecycleItem。executeNonLifecycleItem方法如下private void executeNonLifecycleItem(NonNull ClientTransaction transaction, NonNull ClientTransactionItem item, boolean shouldExcludeLastLifecycleState) { final IBinder token item.getActivityToken(); ActivityClientRecord r mTransactionHandler.getActivityClient(token); if (token ! null r null mTransactionHandler.getActivitiesToBeDestroyed().containsKey(token)) { // The activity has not been created but has been requested to destroy, so all // transactions for the token are just like being cancelled. Slog.w(TAG, Skip pre-destroyed transaction item:\n item); return; } if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) Resolving callback: item); final int postExecutionState item.getPostExecutionState(); if (item.shouldHaveDefinedPreExecutionState()) { final int closestPreExecutionState mHelper.getClosestPreExecutionState(r, postExecutionState); if (closestPreExecutionState ! UNDEFINED) { cycleToPath(r, closestPreExecutionState, transaction); } } item.execute(mTransactionHandler, mPendingActions); item.postExecute(mTransactionHandler, mPendingActions); if (r null) { // Launch activity request will create an activity record. r mTransactionHandler.getActivityClient(token); } if (postExecutionState ! UNDEFINED r ! null) { cycleToPath(r, postExecutionState, shouldExcludeLastLifecycleState, transaction); } }重点看item.execute(mTransactionHandler, mPendingActions); 这句代码。启动事务LaunchActivityItem的execute方法如下final ActivityClientRecord r new ActivityClientRecord(mActivityToken, mIntent, mIdent,mInfo, mOverrideConfig, ...);---- LaunchActivityItem 是从 SystemServer 的 LaunchActivityItem.obtain(...) 打包过来的经过 Binder 传输后它的字段在 App 端被还原。这一行把这些字段组装成 App 端真正能用的 ActivityClientRecord。ActivityClientRecord 是 App 端的“Activity 记录”可以理解为 SystemServer 侧 ActivityRecord 的客户端镜像。关键字段mActivityToken就是 SystemServer 侧的 r.token两边靠它关联同一个 ActivitymIntent、mInfo启动的 Intent 和 ActivityInfomState、mPersistentState保存的状态用于恢复mPendingResults、mPendingNewIntents启动时要投递的结果和新 Intent。然后client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);这里的 client 是 ClientTransactionHandler 类型实际对象就是 ActivityThread因为 ActivityThread extends ClientTransactionHandler。所以这一行就是调用 ActivityThread.handleLaunchActivity(...)。ActivityThread的handleLaunchActivity方法如下Override public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, int deviceId, Intent customIntent) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged true; if (r.profilerInfo ! null) { mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); } // Make sure we are running with the most recent config and resource paths. applyPendingApplicationInfoChanges(r.activityInfo.packageName); mConfigurationController.handleConfigurationChanged(null, null); updateDeviceIdForNonUIContexts(deviceId); if (localLOGV) Slog.v( TAG, Handling launch of r); // Initialize before creating the activity if (ThreadedRenderer.sRendererEnabled (r.activityInfo.flags ActivityInfo.FLAG_HARDWARE_ACCELERATED) ! 0) { HardwareRenderer.preload(); } WindowManagerGlobal.initialize(); // Hint the GraphicsEnvironment that an activity is launching on the process. GraphicsEnvironment.hintActivityLaunch(); final Activity a performLaunchActivity(r, customIntent); if (a ! null) { r.createdConfig new Configuration(mConfigurationController.getConfiguration()); reportSizeConfigurations(r); if (!r.activity.mFinished pendingActions ! null) { pendingActions.setOldState(r.state); pendingActions.setRestoreInstanceState(true); pendingActions.setCallOnPostCreate(true); } // Trigger ActivityWindowInfo callback if first launch or change from relaunch. handleActivityWindowInfoChanged(r); } else { // If there was an error, for any reason, tell the activity manager to stop us. ActivityClient.getInstance().finishActivity(r.token, Activity.RESULT_CANCELED, null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } return a; }final Activity a performLaunchActivity(r, customIntent); 这句代码是重点。然后看performLaunchActivity这个方法太庞大。前面是准备 ActivityInfo 和 ClassLoader然后创建activity对象里面最终是调用反射构造activity对象。然后重点看activity.attach方法attach() 内部会做几件关键事创建 PhoneWindow、设置 WindowManager、调用 attachBaseContext() 把 ContextImpl 注入进去。这是 Activity 从“裸对象”变成“有 Context 的 Activity”的分界点也是 Application 和 Activity 共享同一套 Context 体系的连接处。然后重点看这一句代码mInstrumentation.callActivityOnCreate(activity, r.state);callActivityOnCreate里面最终会调用activity的onCrate方法。这一行最终回调到自己写的 Activity.onCreate()。到这里跨进程启动指令的完整旅程就结束了——SystemServer 发出的 LaunchActivityItem经过 Binder、H、TransactionExecutor最终到onCreate。ok. 回顾了下从ActivityThread的main方法开发main里面调用attach方法中间经过很长的调用链最终执行到了activity的onCreate。 调用链实在太长细节很容易忘总结下如下┌─────────────────────────── Zygote fork ───────────────────────────┐│ ││ App 进程 (主线程) ││ ActivityThread.main() ││ └─ attach() ││ └─ mgr.attachApplication(mAppThread, startSeq) ────────────┼── Binder ──┐│ │ │└────────────────────────────────────────────────────────────────────┘ ││┌─────────────────────────── system_server ────────────────────────────────────────┘││ AMS.attachApplication()│ └─ attachApplicationLocked(thread, pid, uid, startSeq)│ ├─ thread.asBinder().linkToDeath(adr, 0) ← 监听 App 死亡│ ├─ thread.bindApplication(...) ──────────────┼── Binder ──┐ (oneway)│ └─ app.makeActive(thread, mProcessStats) ← 通道登记│ │└────────────────────────────────────────────────────────────────────┘│┌─────────────────────────── App 进程 (Binder 线程) ──────────────────┘││ ApplicationThread.bindApplication()│ └─ queueOrSendMessage(H.BIND_APPLICATION, data)│├─────────────── 切主线程 ───────────────┐│ ││ App 进程 (主线程) ▼│ H.handleMessage(BIND_APPLICATION)│ └─ handleBindApplication(data)│ ├─ app data.info.makeApplicationInner(...) ← Application 实例│ ├─ installContentProviders(app, ...) ← Provider 先于 onCreate│ ├─ mInstrumentation.callApplicationOnCreate(app) ← Application.onCreate()│ └─ mgr.finishAttachApplication(startSeq, ...) ── Binder ──┐│ │└────────────────────────────────────────────────────────────────────┘│┌─────────────────────────── system_server ──────────────────────────┘││ AMS.finishAttachApplicationInner()│ └─ mAtmInternal.attachApplication(wpc) ← LocalServices同进程│ └─ ATMS.LocalService.attachApplication(wpc)│ └─ RootWindowContainer.attachApplication(wpc)│ └─ AttachApplicationHelper.process(app)│ └─ accept() → forAllActivities(this) → test(r)│ └─ realStartActivityLocked(r, app, andResume, ...)│ ├─ LaunchActivityItem.obtain(...) ← 启动指令│ ├─ ResumeActivityItem.obtain(...) ← 目标状态│ └─ ClientTransaction.schedule()│ └─ mClient.scheduleTransaction(t) ── Binder ──┐│ │└─────────────────────────────────────────────────────────────────────────────────────┘│┌─────────────────────────── App 进程 (Binder 线程) ───────────────────────────────────┘││ ApplicationThread.scheduleTransaction()│ └─ ActivityThread.scheduleTransaction() ← 实际在父类 ClientTransactionHandler│ └─ sendMessage(H.EXECUTE_TRANSACTION, transaction)│├─────────────── 切主线程 ───────────────┐│ ││ App 进程 (主线程) ▼│ H.handleMessage(EXECUTE_TRANSACTION)│ └─ TransactionExecutor.execute()│ └─ executeTransactionItems()│ └─ executeNonLifecycleItem()│ └─ LaunchActivityItem.execute()│ └─ ActivityThread.handleLaunchActivity()│ └─ performLaunchActivity()│ ├─ mInstrumentation.newActivity(...) ← 反射创建│ ├─ activity.attach(...) ← 注入 Context│ └─ mInstrumentation.callActivityOnCreate(...) ← Activity.onCreate()压缩成六个阶段整条链路很长但本质上只有三次关键切换整条链路再长本质上只有三次关键切换1、App → 系统attachApplicationApp 把 ApplicationThread 这个 Binder 对象交给系统。2、系统 → AppbindApplication 和 scheduleTransaction系统通过 ApplicationThread 代理反向调用 App。3、Binder 线程 → 主线程两次 sendMessage(H.XXX)分别在 bindApplication 和 scheduleTransaction 之后把工作从 Binder 线程池抛给主线程。一句话记忆attach 交通道 → bindApplication 造 Application → finishAttachApplication 报完成 → realStartActivityLocked 发事务 → LaunchActivityItem 造 Activity。 两次 Binder 往返两次 H 切主线程起点是 ActivityThread.main()终点是 Activity.onCreate()。
RELATED

相关推荐

课堂笔记4

课堂笔记4

课前练习求任意一个三位数&#xff0c;个十百位相加值#include <stdio.h>int main(){ int a,b,c,m,sum;printf("请输入任意一个三位数m")&#xff1b;scanf("%d",&m);am%10;bm/10%10;cm/100;sumabc;printf("%d\n",sum);return 0;}正…

📅 2026/11/1 1:55:44
RAG二 文档切分实战:从语义分层到长度优化

RAG二 文档切分实战:从语义分层到长度优化

1. 背景与目标在构建知识库或 RAG 检索链路时&#xff0c;Markdown 文档的切分质量直接决定了后续向量召回的效果。本文围绕一个基于 LangGraph 的导入流程节点&#xff0c;讲解如何先按标题做语义切分&#xff0c;再对超长块做递归二次切割&#xff0c;最终产出结构清晰、长度…

📅 2026/11/1 1:55:44
单链表从入门到实战:概念、结构与 C 语言接口实现全解析

单链表从入门到实战:概念、结构与 C 语言接口实现全解析

目录 1. 链表的定义 1.1 什么是链表1.2 什么是节点1.3 节点的结构体代码1.4 节点和链表的关系 2. 链表的性质3. 链表的优势4. 链表的打印5. 单链表 5.1 申请节点5.2 链表尾插5.3 链表头插5.4 链表头删5.5 链表尾删5.6 在指定位置前插入5.7 在指定位置后插入5.8 指定位置删除5.…

📅 2026/11/1 1:55:44
MORE NEWS

更多资讯

📰

启动报Port 8088 was already in use?先查是谁占的

启动报Port 8088 was already in use&#xff1f;先查是谁占的 项目启动报 Port 8088 was already in use&#xff0c;意思很直白&#xff1a;这个端口已经有人占了。 先说原理&#xff1a;端口是"门牌号"&#xff0c;一间房只住一个进程 端口就是一台机器上的门牌号…

📰

担心文档上云?本地运行的办公AI才敢放心用

单位上周开了个会&#xff0c;主题是"AI 提效"&#xff0c;散会时领导补了一句&#xff1a;涉及客户资料的文档&#xff0c;不许往云端传。这话一出&#xff0c;会议室里本来跃跃欲试的同事全蔫了——大家平时用的那些在线 AI&#xff0c;文档一上传就不知道存哪儿去…

📰

先能用,再好用:从烂尾复盘到两周上线,全栈项目的‘原型—快速迭代‘方法论

先能用&#xff0c;再好用&#xff1a;从烂尾复盘到两周上线&#xff0c;全栈项目的“原型—快速迭代”方法论 全栈学习路径的文章已经很多了&#xff1a;怎么选技术栈、怎么搭环境、怎么记文档&#xff0c;几乎每个方向都有人写。但一个更扎心的问题很少有人正面讨论——为什…

📰

深度思考模式把 ARC-AGI-2 从 17.6% 拉到 45.1%:对照 Gemini 3 Pro 的三份能力评测,看‘会思考‘改写了哪些边界

深度思考模式把 ARC-AGI-2 从 17.6% 拉到 45.1%&#xff1a;对照 Gemini 3 Pro 的三份能力评测&#xff0c;看“会思考”改写了哪些边界 一、先说结论&#xff1a;变强的不是“知识”&#xff0c;而是“解法” 每次新模型发布&#xff0c;评测榜单都会涨几个点&#xff0c;大…

📰

1.c++入门篇

1.c中的关键字asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseenummutablestaticunionwchar_tcatchexplicitnamespacestatic_castunsigneddefaultcharexportnewstructusingfriendclassext…

📰

《江灯合声》:有可行的分框版,也仍可以选择连续鸣谢

武汉江岸区栎坡合唱团在免费节目册《江灯合声》中&#xff0c;以表格集中鸣谢资助者。各家共同要求改为独立小框&#xff0c;团里仍想保留表格。现有全名与支持事项清楚可见&#xff0c;双方此前未承诺具体排版。我支持保留表格。补充的试排材料让选择更具体&#xff1a;分框能…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬