首页 > 应用开发 > Javascript > Android 组件初始化顺序详解
本文档基于实际项目测试和官方文档编写,旨在深入理解 Android 系统中 Application、ContentProvider 和 App Startup (InitializationProvider) 的初始化时机与顺序。
当 Android 应用启动时,组件的初始化遵循以下顺序:
┌─────────────────────────────────────────────────────────────────┐
│
1. Application 构造函数 │
├─────────────────────────────────────────────────────────────────┤
│
2. Application
.attachBaseContext() │
├─────────────────────────────────────────────────────────────────┤
│
3. ContentProvider
.attachInfo() │
│ └─ 包含 InitializationProvider (App Startup) │
│ └─ 按依赖顺序执行所有 Initializer │
├─────────────────────────────────────────────────────────────────┤
│
4. 其他 ContentProvider (按 initOrder 排序) │
├─────────────────────────────────────────────────────────────────┤
│
5. Application
.onCreate() │
├─────────────────────────────────────────────────────────────────┤
│
6. Activity 生命周期 │
└─────────────────────────────────────────────────────────────────┘
根据 Android 官方文档和源码分析,
ContentProvider 的初始化顺序由
android:initOrder 属性决定,而非字母顺序。
官方原文: "The order in which the content provider should be instantiated, relative to other content providers hosted by the same process. When there are dependencies among content providers, setting this attribute for each of them ensures that they are created in the order required by those dependencies. The value is a simple integer, with higher numbers being initialized first."
翻译:
android:initOrder 属性定义了 ContentProvider 在同一进程中的实例化顺序。当 ContentProvider 之间存在依赖关系时,设置此属性可以确保它们按照依赖关系的顺序创建。值是整数,
数值越大越先初始化。
| 属性 | 说明 |
|---|---|
| 名称 |
android:initOrder |
| 类型 | 整数 (integer) |
| 默认值 | 0 |
| 规则 | 值越大,越先初始化 |
<!-- 第一个被初始化的 Provider (initOrder=100) -->
<
provider
android:name=
".FirstProvider"
android:authorities=
"com.example.first"
android:initOrder=
"100" />
<!-- 第二个被初始化的 Provider (initOrder=50) -->
<
provider
android:name=
".SecondProvider"
android:authorities=
"com.example.second"
android:initOrder=
"50" />
<!-- 第三个被初始化的 Provider (默认值0) -->
<
provider
android:name=
".ThirdProvider"
android:authorities=
"com.example.third" />
初始化顺序:
FirstProvider →
SecondProvider →
ThirdProvider
如果多个 ContentProvider 都没有设置
initOrder,它们的初始化顺序是
不确定的,可能取决于:
因此,如果需要确保特定顺序,务必显式设置
android:initOrder 属性。
App Startup 是 AndroidX 提供的一个库,允许在应用启动时统一、显式地初始化组件。它使用
InitializationProvider (一个特殊的 ContentProvider) 来发现和调用初始化代码。
InitializationProvider.onCreate() 被调用通过
Initializer 接口的
dependencies() 方法声明依赖:
class
FirstInitializer :
Initializer<
Unit> {
override
fun
dependencies
(): List<Class<
out Initializer<*>>> = emptyList()
}
class
SecondInitializer :
Initializer<
Unit> {
override
fun
dependencies
(): List<Class<
out Initializer<*>>> {
return listOf(FirstInitializer::
class.java)
}
}
class
ThirdInitializer :
Initializer<
Unit> {
override
fun
dependencies
(): List<Class<
out Initializer<*>>> {
return listOf(SecondInitializer::
class.java)
}
}
执行顺序:
FirstInitializer →
SecondInitializer →
ThirdInitializer
无依赖关系的 Initializer 之间的顺序是不保证的,App Startup 内部可能会按注册顺序、随机顺序或其他逻辑执行。
<
provider
android:name=
"androidx.startup.InitializationProvider"
android:authorities=
"${applicationId}.androidx-startup"
android:exported=
"false"
tools:node=
"merge">
<!-- Initializer 1 -->
<
meta-data
android:name=
"com.example.ThirdInitializer"
android:value=
"androidx.startup" />
<!-- Initializer 2 -->
<
meta-data
android:name=
"com.example.SecondInitializer"
android:value=
"androidx.startup" />
<!-- Initializer 3 -->
<
meta-data
android:name=
"com.example.FirstInitializer"
android:value=
"androidx.startup" />
</
provider>
注意:Manifest 中的声明顺序
不影响实际执行顺序,实际顺序由
dependencies() 方法决定。
class
MyApplication :
Application() {
// 1. 最先被调用
override
fun
attachBaseContext
(base:
Context) {
super.attachBaseContext(base)
}
// 2. 在所有 ContentProvider 初始化完成后调用
override
fun
onCreate
() {
super.onCreate()
}
}
attachBaseContext() ──┐
├── 在 ContentProvider 之前
attachBaseContext()完成─┘
ContentProvider
.onCreate() ──┐
├── App Startup 在此处执行
InitializationProvider
.onCreate() ──┘
其他 ContentProvider
.onCreate() (如果有)
Application
.onCreate() ──┐
├── 在所有 ContentProvider 完成后
Application
.onCreate()完成 ──┘
基于本项目的实际运行日志:
14:29:45.676 Application.attachBaseContext() 开始执行
14:29:45.676 Application.attachBaseContext() 执行完毕
14:29:45.685 【FirstInitializer】开始执行 - 初始化基础组件
14:29:45.736 【FirstInitializer】执行完毕
14:29:45.741 WM-WrkMgrInitializer: Initializing WorkManager...
14:29:45.787 【SecondInitializer】开始执行 - 初始化 DataStore
14:29:45.831 【SecondInitializer】执行完毕
14:29:45.831 【ThirdInitializer】开始执行 - 初始化配置管理器
14:29:45.870 【ThirdInitializer】执行完毕
14:29:45.870 【FourInitializer】开始执行 - 初始化
14:29:45.900 【FourInitializer】执行完毕
14:29:45.902 ContentProvider.attachInfo() - authority: com.example.initorderdemo.provider
14:29:45.903 ContentProvider.onCreate() 开始执行
14:29:45.913 ContentProvider.onCreate() 执行完毕
14:29:45.914 Application.onCreate() 开始执行
14:29:45.915 Application.onCreate() 执行完毕
使用
android:initOrder 属性:
<
provider
android:name=
".MyProvider"
android:initOrder=
"50" />
使用
dependencies() 方法显式声明依赖:
class
MyInitializer :
Initializer<
Unit> {
override
fun
dependencies
(): List<Class<
out Initializer<*>>> {
return listOf(OtherInitializer::
class.java)
}
}
ContentProvider.onCreate() 在主线程执行,会阻塞应用启动。
多个 SDK 同时使用各自定义的 ContentProvider 会导致:
推荐方案:统一使用 App Startup 管理初始化。
| 组件 | 初始化顺序规则 | 如何控制 |
|---|---|---|
| ContentProvider | 按
android:initOrder 排序,值越大越先执行 |
设置
android:initOrder 属性 |
| App Startup Initializer | 有依赖的按依赖顺序执行,无依赖的不保证顺序 | 使用
dependencies() 方法声明依赖 |
| Application | 在所有 ContentProvider 之后初始化 | 不可控制 |
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048944/viewspace-3114187/ ,如需转载,请注明出处,否则将追究法律责任。