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 实例

参考资料

相关推荐
不爱说话郭德纲6 小时前
告别漫长的HbuilderX云打包排队!uni-app x 安卓本地打包保姆级教程(附白屏、包体积过大排坑指南)
android·前端·uni-app
程序员清风9 小时前
程序员兼职必看:靠谱软件外包平台挑选指南与避坑清单!
java·后端·面试
皮皮林55110 小时前
利用闲置 Mac 从零部署 OpenClaw 教程 !
java
Sinclair11 小时前
简单几步,安卓手机秒变服务器,安装 CMS 程序
android·服务器
A0微声z13 小时前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
雮尘14 小时前
手把手带你玩转Android gRPC:一篇搞定原理、配置与客户端开发
android·前端·grpc
ktl15 小时前
Android 编译加速/优化 80%:一个文件搞定,零侵入零配置
android
华仔啊16 小时前
挖到了 1 个 Java 小特性:var,用完就回不去了
java·后端
SimonKing16 小时前
SpringBoot整合秘笈:让Mybatis用上Calcite,实现统一SQL查询
java·后端·程序员
alexhilton1 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack