Android 应用启动 -> Android 多种方式启动同一进程,Application.onCreate() 会多次执行吗?

Android 多种方式启动同一进程,Application.onCreate() 会多次执行吗?

一、问题场景

在 Android 开发中,我们经常会遇到这样的场景:

  1. A 进程 通过 bindService() 预启动 B 进程(用于预热/预加载)
  2. 几十毫秒后,A 进程 又通过 startActivity() 启动 B 进程 的某个 Activity

问题 :B 进程的 Application.onCreate() 会多次执行吗?

二、答案

不会。 Application.onCreate() 在进程生命周期内只会执行一次。

三、原理分析

3.1 Android 进程与 Application 的关系

复制代码
┌─────────────────────────────────────────┐
│              Android 进程                │
│  ┌───────────────────────────────────┐  │
│  │         Application 实例           │  │
│  │    (整个进程只有一个,单例)          │  │
│  └───────────────────────────────────┘  │
│                                         │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐  │
│  │Activity │  │Service  │  │Receiver │  │
│  └─────────┘  └─────────┘  └─────────┘  │
└─────────────────────────────────────────┘

关键点:

  • 每个 Android 进程对应唯一一个 Application 实例
  • Application.onCreate() 在进程创建时调用,且仅调用一次
  • 无论通过什么方式(Service、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 时进程已"热",无需等待初始化,启动更快

七、总结

  1. Android 进程内 Application 是单例 ,onCreate() 只执行一次
  2. 无论通过什么方式启动 (bindService、startActivity、sendBroadcast),只要是同一进程,Application 不会重复初始化
  3. bindService 预启动是一种有效的冷启动优化手段,可以提前完成进程初始化
  4. 多进程配置 时,每个进程有独立的 Application 实例

参考资料:

相关推荐
code2cat2 小时前
Java工具篇之Maven:从pom.xml到测试通过的JAR
xml·java·maven
wuminyu8 小时前
JVM规范学习总结:解释器与JIT编译器如何处理JVM字节码
java·linux·c语言·jvm·c++
txxzjmzlh8 小时前
SpringBoot 配置⽂件
java·spring boot·spring
小徐不徐说8 小时前
序列化与反序列化:把 C++ 对象可靠地保存下来
开发语言·数据库·c++·php
ragnwang9 小时前
Notes: Python pybind11 import C++ module
开发语言·c++·python
Wang's Blog9 小时前
Java 项目实战: 交友项目 - 搜索附近的功能概述和分析
java·开发语言·交友
骑着蜗牛撵大象3279 小时前
大模型 Agent 的沙箱护栏:gVisor 隔离、出口白名单与审计闭环
java·开发语言·jvm·安全·agent沙箱·gvisor·microvm
独泪了无痕9 小时前
Hutool之LocalDateTimeUtil:让时间间隔操作如虎添翼
java
Dxy123931021610 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷10 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++