一、概念
将所有用于初始化的 ContentProvider 合并成一个,从而使App的启动速度变得更快。
引入过多的第三方库会导致Application中初始化繁琐,因此很多库利用ContentProvider自动onCreate()的特性来初始化获取Context,但是ContentProvider属于重量级操作创建过多会非常影响APP的启动速度。
Startup内部也创建了一个ContentProvider,并提供了一套用于初始化的标准。然后对于其他第三方库来说,你们就不需要再自己创建ContentProvider了,都按我的这套标准进行实现就行了,我可以保证你们的库在App启动之前都成功进行初始化。
二、使用
2.1 添加依赖
implementation("androidx.startup:startup-runtime:1.1.1")
2.2 实现初始化器 Initializer<T>
2.2.1 对单个库实现
初始化 WorkManager。
class WorkManagerInitializer : Initializer<WorkManager> {
override fun create(context: Context): WorkManager {
val configuration = Configuration.Builder().build()
WorkManager.initialize(context, configuration)
return WorkManager.getInstance(context)
}
override fun dependencies(): List<Class<out Initializer<*>>> {
//WorkManager 不依赖于其他库返回空列表
return emptyList()
}
}
2.2.2 一个库又依赖了另一个库
初始化的 ExampleLogger 依赖于 WorkManager,需要先初始化 WorkManager 再初始化自己。
class ExampleLoggerInitializer : Initializer<ExampleLogger> {
override fun create(context: Context): ExampleLogger {
return ExampleLogger(WorkManager.getInstance(context))
}
override fun dependencies(): List<Class<out Initializer<*>>> {
//定义依赖关系,以便在初始化WorkManagerInitializer后初始化自己
return listOf(WorkManagerInitializer::class.java)
}
}
2.2.3 同时对多个库实现
class MixInitializer : Initializer<Any> {
override fun create(context: Context): Any {
AAAUtils.init(context)
BBBUtils.init(context)
return Unit
}
override fun dependencies(): List<Class<out Initializer<*>>> {
return emptyList()
}
}
2.3 注册 InitializationProvider
WorkManagerInitializer 是 ExampleLoggerInitializer 的依赖项,ExampleLoggerInitializer 能被检测到那么 WorkManagerInitializer 也可被检测到,不需要再为 WorkManagerInitializer 添加 <meta-data> 标签。tools:node="merge" 属性可确保清单合并工具正常解析冲突的条目。
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- 这个标签是初始化器能被检测到的关键 -->
<meta-data android:name="com.example.ExampleLoggerInitializer"
android:value="androidx.startup" />
</provider>
2.4 手动初始化(延迟初始化)
应用启动时,InitializationProvider 对象会使用名为 AppInitializer 的实体在应用启动时自动发现并运行组件初始化程序。也可以直接使用 AppInitializer 以便手动初始化应用在启动时不需要的组件,达到“延迟初始化”目的。
2.4.1 停用单个库的自动初始化
从清单中移除该库的 <meta-data> 标签,不是直接删除,而是使用 tools:node="remove" 以确保合并工具也会从所有其他合并后的清单文件中移除该条目。
- 注意,该库移除后,它的依赖项不会再自动初始化。
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data android:name="com.example.ExampleLoggerInitializer"
tools:node="remove" />
</provider>
2.4.2 为所有库停用自动初始化
从清单中移除 InitializationProvider 的整个条目。
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
2.4.3 手动初始化
AppInitializer.getInstance(context)
.initializeComponent(ExampleLoggerInitializer::class.java)
三、优化第三方SDK
一些sdk在 AndroidManifest 里面注册了自己的 xxSDkProvider,然后在 xxSDkProvider 的 onCreate 方面里面进行初始化,确实调用者不需要自己初始化了,可却增加了启动耗时, 我们可以打开 Apk,看一下最终merge的 AndroidManiest 里面有多少 provider,看一下是否有这样的骚操作,往往这里容易忽视,这种情况可以使用谷歌App Startup来收敛ContentProvider