Android 多种方式启动同一进程,Application.onCreate() 会多次执行吗?
一、问题场景
在 Android 开发中,我们经常会遇到这样的场景:
- A 进程 通过
bindService()预启动 B 进程(用于预热/预加载) - 几十毫秒后,A 进程 又通过
startActivity()启动 B 进程 的某个Activity
问题 :B 进程的 Application.onCreate() 会多次执行吗?
二、答案
不会。 Application.onCreate() 在进程生命周期内只会执行一次。
三、原理分析
3.1 Android 进程与 Application 的关系
┌─────────────────────────────────────────┐
│ Android 进程 │
│ ┌───────────────────────────────────┐ │
│ │ Application 实例 │ │
│ │ (整个进程只有一个,单例) │ │
│ └───────────────────────────────────┘ │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │Activity │ │Service │ │Receiver │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────────┘
关键点:
- 每个
Android进程对应唯一一个Application实例 Application.onCreate()在进程创建时调用,且仅调用一次- 无论通过什么方式(S
ervice、Activity、BroadcastReceiver、ContentProvider)触发进程启动,Application只会初始化一次
3.2 进程启动流程
第一次 bindService() 触发:
┌──────────┐ bindService() ┌──────────┐
│ A 进程 │ ─────────────────► │ Zygote │
└──────────┘ └────┬─────┘
│ fork
▼
┌──────────────┐
│ B 进程 │
│ │
│ 1. 创建进程 │
│ 2. Application.onCreate() ✅
│ 3. 创建 Service │
│ 4. onBind() │
└──────────────┘
几十毫秒后 startActivity() 触发:
┌──────────┐ startActivity() ┌──────────────┐
│ A 进程 │ ─────────────────► │ B 进程 │
└──────────┘ │ (已存在) │
│ │
│ 进程已存在, │
│ 不会重新创建 │
│ │
│ 直接创建 Activity │
│ ❌ 不会再执行 Application.onCreate()
└──────────────┘
3.3 源码层面分析
在 ActivityThread 中,进程启动时会调用 handleBindApplication():
java
// ActivityThread.java 简化逻辑
private void handleBindApplication(AppBindData data) {
// 创建 Application 实例(只会执行一次)
Application app = data.info.makeApplication(false, mInstrumentation);
// 调用 onCreate(只会执行一次)
mInstrumentation.callApplicationOnCreate(app);
}
后续的组件启动(Activity、Service 等)都是在已有进程 内创建,不会重复触发 Application 的创建。
四、验证方法
可以通过日志验证:
kotlin
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Log.d("MyApp", "onCreate called, pid=${Process.myPid()}, time=${System.currentTimeMillis()}")
}
}
测试结果 :无论 bindService 和 startActivity 调用多少次、间隔多短,onCreate 日志只会出现一次。
五、相关场景总结
| 场景 | Application.onCreate() 执行次数 |
|---|---|
| bindService → startActivity(同进程) | 1 次 |
| startActivity → bindService(同进程) | 1 次 |
| 多次 startActivity(同进程) | 1 次 |
| 多次 bindService(同进程) | 1 次 |
| 进程被杀死后重新启动 | 再执行 1 次 |
| 不同进程(android:process 配置不同) | 每个进程各 1 次 |
六、注意事项
6.1 多进程情况
如果 Service 和 Activity 配置了不同的进程 ,则各自进程的 Application.onCreate() 会分别执行:
xml
<!-- AndroidManifest.xml -->
<service
android:name=".MyService"
android:process=":remote" /> <!-- 独立进程 -->
<activity
android:name=".MyActivity" /> <!-- 主进程 -->
此时 bindService 和 startActivity 会触发两个不同进程 ,Application.onCreate() 会执行两次(每个进程各一次)。
6.2 预启动优化场景
问题中的场景(bindService 预启动)是一种常见的冷启动优化手段:
kotlin
// 预启动:提前拉起目标进程,让其完成初始化
fun preLaunch() {
val intent = Intent().setComponent(ComponentName("pkg", "pkg.PreloadService"))
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
// 正式启动:此时进程已存在,启动更快
fun launch() {
startActivity(Intent().setComponent(ComponentName("pkg", "pkg.MainActivity")))
}
这种方式的优势:
- 第一次
bindService触发进程创建 +Application初始化 - 后续
startActivity时进程已"热",无需等待初始化,启动更快
七、总结
- Android 进程内 Application 是单例 ,
onCreate()只执行一次 - 无论通过什么方式启动 (
bindService、startActivity、sendBroadcast),只要是同一进程,Application不会重复初始化 - bindService 预启动是一种有效的冷启动优化手段,可以提前完成进程初始化
- 多进程配置 时,每个进程有独立的
Application实例
参考资料: