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()}")
    }
}

测试结果 :无论 bindServicestartActivity 调用多少次、间隔多短,onCreate 日志只会出现一次

五、相关场景总结

场景 Application.onCreate() 执行次数
bindService → startActivity(同进程) 1 次
startActivity → bindService(同进程) 1 次
多次 startActivity(同进程) 1 次
多次 bindService(同进程) 1 次
进程被杀死后重新启动 再执行 1 次
不同进程(android:process 配置不同) 每个进程各 1 次

六、注意事项

6.1 多进程情况

如果 ServiceActivity 配置了不同的进程 ,则各自进程的 Application.onCreate() 会分别执行:

xml 复制代码
<!-- AndroidManifest.xml -->
<service 
    android:name=".MyService"
    android:process=":remote" />  <!-- 独立进程 -->

<activity 
    android:name=".MyActivity" /> <!-- 主进程 -->

此时 bindServicestartActivity 会触发两个不同进程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 实例

参考资料

相关推荐
沐知全栈开发2 小时前
JavaScript 计时事件
开发语言
期待のcode2 小时前
Java 共享变量的内存可见性问题
java·开发语言
2501_916008892 小时前
iOS 开发助手工具,设备信息查看、运行日志、文件管理等方面
android·ios·小程序·https·uni-app·iphone·webview
会游泳的石头2 小时前
深入剖析 Java 长连接:SSE 与 WebSocket 的实战陷阱与优化策略
java·开发语言·websocket
yutian06062 小时前
TI-C2000 系列 TMS320F2837X 控制律加速器(CLA)应用
开发语言·ti·ti c2000
夕阳之后的黑夜2 小时前
Python脚本:为PDF批量添加水印
开发语言·python·pdf
TheNextByte12 小时前
如何在Android上恢复已删除的文件
android·gitee
lllljz2 小时前
blenderGIS出现too large extent错误
java·服务器·前端
女王大人万岁2 小时前
Go标准库 path 详解
服务器·开发语言·后端·golang