目录
一、流程对比图
以下为 冷启动 和 热启动 的流程对比图:
二、冷启动(Cold Launch)
定义:应用进程完全不存在,系统需从头创建进程并初始化组件。
APP冷启动时序图:
详细流程:
Android 应用冷启动流程是一个复杂的系统级协作过程,涉及多个关键组件和源码模块。以下是详细的流程解析及源码分析:
2.1 用户点击应用图标(Launcher 触发)
Launcher 是一个特殊的 Android 应用,负责管理主屏幕和应用快捷方式。
点击图标时,Launcher 通过
startActivity()
发起启动请求。目标 Activity 的 Intent 会被设置为FLAG_ACTIVITY_NEW_TASK
,表示新任务栈。
源码关键点:
Launcher
调用startActivitySafely()
,最终通过Instrumentation.execStartActivity()
发起请求。
2.2 AMS 处理启动请求
ActivityManagerService (AMS) 是 Android 核心服务,负责管理 Activity 生命周期和任务栈。
AMS 检查目标 Activity 是否存在、权限是否满足,并决定是否创建新进程。
源码路径:
请求通过 Binder 传递到
ActivityManagerService.startActivity()
。关键类:
ActivityStarter
处理启动逻辑,ActivityStackSupervisor
管理任务栈。
2.3 请求 Zygote 创建新进程
如果目标应用未运行,AMS 通过 Zygote 进程 fork 出新进程。
Zygote 预加载了常用类库和资源,加快进程创建速度。
源码关键点:
ZygoteProcess.start()
通过 Socket 与 Zygote 通信,发送参数(如主类android.app.ActivityThread
)。新进程入口:
ActivityThread.main()
。
2.4 初始化应用进程
ActivityThread 是应用进程的主线程类,负责管理应用组件的生命周期。
源码流程:
入口方法:
ActivityThread.main()
初始化主线程 Looper。public static void main(String[] args) { Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); // 关联到 AMS Looper.loop(); }
绑定到 AMS:通过
attach()
方法,跨进程调用AMS.attachApplication()
,传递ApplicationThread
(Binder 对象,用于 AMS 回调)。
2.5 创建 Application 对象
AMS 通知新进程创建
Application
实例,并调用其onCreate()
。
源码关键点:
ActivityThread.handleBindApplication()
处理 AMS 的绑定请求:private void handleBindApplication(AppBindData data) { // 1. 创建 LoadedApk(封装 APK 信息) LoadedApk loadedApk = getLoadedApk(data.appInfo); // 2. 创建 ContextImpl ContextImpl appContext = ContextImpl.createAppContext(this, loadedApk); // 3. 创建 Instrumentation Instrumentation instr = new Instrumentation(); // 4. 创建 Application 实例 Application app = loadedApk.makeApplication(false, instr); // 5. 调用 Application.onCreate() instr.callApplicationOnCreate(app); }
2.6 启动目标 Activity
AMS 通过
ApplicationThread
调度启动目标 Activity。
源码流程:
AMS 发送启动请求:
ActivityStackSupervisor.realStartActivityLocked()
。进程内处理:
ActivityThread.scheduleLaunchActivity()
发送LAUNCH_ACTIVITY
消息到主线程 Handler(H
)。创建 Activity 实例:
ActivityThread.handleLaunchActivity()
:private void handleLaunchActivity(ActivityClientRecord r) { // 1. 创建 Activity 实例 Activity activity = mInstrumentation.newActivity(cl, component, r.intent); // 2. 创建 Application 和 ContextImpl Application app = r.packageInfo.makeApplication(false, mInstrumentation); ContextImpl appContext = createBaseContextForActivity(r); // 3. 关联 Activity 和 Context activity.attach(appContext, this, ...); // 4. 调用 Activity.onCreate() mInstrumentation.callActivityOnCreate(activity, r.state); // 5. 执行 onStart() 和 onResume() handleStartActivity() -> handleResumeActivity(); }
2.7 执行 Activity 生命周期
Instrumentation 负责监控 Activity 生命周期调用。
关键生命周期回调顺序:
onCreate()
→onStart()
→onResume()
。
源码关键点:
ActivityThread.performLaunchActivity()
触发onCreate()
。ActivityThread.handleResumeActivity()
触发onResume()
,并添加ViewRootImpl
启动 UI 绘制。
2.8 UI 绘制流程
ViewRootImpl 负责管理 UI 渲染,触发
measure()
→layout()
→draw()
。Activity 变为可见状态后,
onWindowFocusChanged(true)
被调用。
2.9 关键类与机制总结
Zygote:进程孵化器,加速进程创建。
AMS:全局管理 Activity 和进程。
ActivityThread:应用主线程,管理组件生命周期。
ApplicationThread:Binder 桥梁,用于 AMS 与应用进程通信。
Instrumentation:监控和控制组件生命周期。
2.10 冷启动优化:
减少
Application.onCreate()
耗时操作:避免在主线程初始化第三方库。避免主线程阻塞,优化首帧渲染时间(如减少布局层级)。
使用启动主题:替换默认白屏/黑屏,提升用户体验(如设置
windowBackground
)。延迟加载:按需初始化非关键组件(如使用
SplashScreen
)。
三、热启动(Warm Launch)
定义:应用进程仍在后台运行(未被系统回收),直接复用已有进程。
3.1 详细流程:
用户触发
用户从最近任务列表或返回应用。恢复 Activity
若主 Activity 未被销毁,直接调用
Activity.onRestart()
→onStart()
→onResume()
。若 Activity 被销毁但进程存活,重建 Activity(调用
onCreate()
)。
界面切换
WindowManager
将后台 Activity 切换到前台,无需重新布局。
3.2 热启动优化:
避免内存泄漏:防止 Activity 无法回收导致进程驻留。
精简
onResume()
逻辑:减少重复初始化操作。使用
ViewModel
:缓存界面数据,避免重复加载。
四、冷启动 vs 热启动对比
特性 | 冷启动 | 热启动 |
---|---|---|
进程状态 | 进程不存在,需从头创建 | 进程已存在,直接复用 |
耗时 | 较长(100ms~数秒) | 较短(通常 <100ms) |
资源消耗 | 高(CPU、内存) | 低 |
生命周期调用 | Application.onCreate() → Activity.onCreate() |
Activity.onRestart() → onResume() |
五、启动优化工具
ADB 命令
adb shell am start -W <package>/<activity>
输出
TotalTime
和WaitTime
分析启动耗时。Android Profiler
监控 CPU、内存和线程状态,定位耗时操作。Jetpack Macrobenchmark
自动化测试启动性能并生成报告。
六、空白window问题
app启动时,会短暂的一瞬间白屏:
有两种方法:
1. 禁用app启动时window预览的功能
在主题中为首屏activity添加一个注意禁用window预览的功能,并在manifest中使用
<resources>
<!--Base application theme-->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!--Customize your theme here.-->
<item name="colorPrimary">@color/mainColor</item>
<item name="colorPrimaryDark">@color/red</item>
<item name="colorAccent">@color/black</item>
</style>
<!--禁用预览功能主题-->
<style name="AppSpalshNoPreviewTheme" parent="AppTheme">
<item name="android:windowFullscreen">true</item>
<item name="windowNoTitle">true</item>
<!-- <item name="android:windowBackground">@mipmap/wall</item>-->
<item name="android:windowDisablePreview">true</item>
</style>
</resources>
2. 给空白首屏Activity设置一个背景
在style.xml中给SplashActivity添加一个新主题,设置一个背景:
<style name="AppSpalshNoPreviewTheme" parent="AppTheme">
<item name="android:windowFullscreen">true</item>
<item name="windowNoTitle">true</item>
<item name="android:windowBackground">@mipmap/aliyun</item>
<!-- <item name="android:windowDisablePreview">true</item>-->
</style>
会发现点击后,之前的空白页面换成了背景图。
冷启动的介绍可知,app启动过程中,会有如下过程
app启动过程中,显示白屏,首屏第一次绘制完成,就会替换白屏;也就是说在首屏显示之前,都是白屏。所以,要想解决白屏的问题,就要减少白屏显示的时间,也就是说要加快app初始化和首屏绘制的时间。
通过理解冷/热启动机制及优化方法,可显著提升用户体验。如果喜欢,欢迎点赞!
参考: