整理自模拟面试,覆盖应用启动流程 / 冷启动热启动 / Zygote / Activity 生命周期与绘制链路 / SurfaceFlinger / 多进程 / SharedPreferences 与 DataStore
一句话:Launcher 发起启动请求,系统服务调度目标组件,必要时先创建应用进程,再创建 Application 和首页 Activity,最后完成 View 绘制并由系统合成显示。
Launcher 构造带 MAIN + LAUNCHER 的启动 IntentActivityTaskManagerService / ActivityManagerServiceZygote fork 新进程ActivityThread.main(),初始化主线程 Looper 和消息队列bindApplication,创建 Application 并执行 Application#onCreate()ActivityActivity,依次执行 onCreate -> onStart -> onResumesetContentView 创建 DecorView 和 View 树ViewRootImpl 发起 measure -> layout -> drawSurface 提交,由 SurfaceFlinger 合成后显示到屏幕AMS / ATMSZygoteActivityThread.main()SurfaceFlinger定义:应用进程不存在,需要从创建进程开始走完整启动链路。
典型流程:
无进程 -> 创建进程 -> Application 初始化 -> Activity 创建 -> 首屏绘制
特点:
- 链路最长
- 耗时最高
- 主要成本在进程创建、应用初始化、首帧渲染
定义:应用进程还在,但目标页面需要重新创建或恢复。
典型流程:
有进程 -> 创建/恢复 Activity -> 重新绘制首屏
特点:
- 不需要重新 fork 进程
- 但仍有页面创建和渲染成本
定义:应用进程和页面大多仍在,只是从后台快速切回前台。
典型流程:
有进程/有页面 -> 恢复前台 -> 恢复交互
特点:
- 路径最短
- 用户感知最快
Zygote 为什么能提速一句话:Zygote 通过预加载常用类和资源,再使用 fork + 写时复制 创建应用进程,避免每次从零初始化运行时环境。
Zygote 会预加载 Java 核心类、Android Framework 类和部分资源应用进程创建时不需要完全重新初始化
fork 创建进程
而是让 Zygote 直接 fork 子进程
写时复制
fork 后父子进程最开始共享内存页Zygote 提速的本质是:预加载 + fork + Copy-on-Write
一句话:生命周期负责组件状态切换,绘制流程负责把界面真正显示出来,两者在 setContentView 和 ViewRootImpl 这一层串联。
ActivityonCreateonCreate 中调用 setContentViewDecorView 和 View 树onStartonResumeViewRootImpl 发起 performTraversalsmeasure -> layout -> drawsetContentView 不等于页面已经显示,只是把布局树准备好onResume 不等于用户一定已经看到首帧,因为绘制可能还没完成onCreate / onResume 后被耗时任务阻塞,仍可能出现白屏或卡顿Application#onCreate()、首页 Activity 初始化、首帧前同步任务三处切SurfaceFlinger 是什么一句话:SurfaceFlinger 是 Android 图形系统中的系统合成器,负责把各个窗口和应用提交的图层合成为最终屏幕画面。
SurfaceApp 执行 draw
-> 绘制到自己的 Surface Buffer
-> Buffer 交给 SurfaceFlinger
-> SurfaceFlinger 合成所有窗口图层
-> 显示到屏幕
WindowManagerService:更偏窗口管理,负责窗口添加、层级、焦点、布局SurfaceFlinger:更偏图形合成,负责最终上屏画面View.draw() 不是直接画到屏幕,而是先画到缓冲区;真正把内容合成上屏的是 SurfaceFlinger
一句话:系统会优先拉起“被启动组件所在的进程”,而不是固定先起主进程;每个进程都有自己独立的运行环境和一份 Application 生命周期。
Activity 在默认进程,就先拉起主进程如果 Launcher Activity 显式声明到 :remote,就先拉起远程进程
每个进程都独立
单例、静态变量、缓存都不共享
Application#onCreate() 会在每个被拉起的进程中执行一次
如果初始化逻辑不分进程,就可能重复初始化 SDK、数据库、埋点
跨进程能力要走 IPC
ApplicationSharedPreferences 为什么早期多进程一致性差一句话:SharedPreferences 主要基于进程内缓存优化读性能,不是为多进程强一致设计的;多个进程各自持有一份内存副本,就容易出现脏读和覆盖写。
MapMODE_MULTI_PROCESSSharedPreferences 承载关键多进程共享状态DataStore 有什么优点一句话:DataStore 是 Jetpack 对轻量本地配置存储的现代化升级,提供了更自然的异步读写、一致性保障和更好的类型安全能力。
Flow减少主线程阻塞风险
一致性更好
单次 edit / updateData 的原子性更清晰
天然响应式
Flow很适合与 ViewModel、StateFlow、Compose 配合
类型安全更好
Proto DataStore 可通过 protobuf 定义结构化字段比字符串 key 更清晰、更稳
错误处理和迁移能力更明确
SharedPreferences 平滑迁移DataStore 通常更合适DataStore 支持多进程吗结论:支持,但不能把普通单进程 DataStore 直接当成天然多进程安全;多进程场景要使用官方提供的多进程支持能力。
DataStore 的一致性建立在“同一份数据由受控实例串行更新”这个前提上DataStore 不等于跨进程共享方案SharedPreferences 在多进程下一致性先天弱DataStore 在单进程下的一致性模型更好Application 多次初始化和 IPC 成本SharedPreferences 与 DataStoreLauncher -> AMS/ATMS -> Zygote -> ActivityThread -> Activity -> ViewRootImpl -> SurfaceFlingerApplicationSharedPreferences 不适合强一致多进程共享,DataStore 更现代但多进程也要专门支持