项目地址: github.com/lwj1994/ini…
前言
Android 启动时有一些初始化的任务(初始化 SDK/ 自己的业务逻辑),项目小的时候,直接放在 Application 中初始化没什么毛病,但是项目大了之后,各种各样的初始化全写在一起就比较混乱,并且这些任务有依赖关系,B 任务需要等 A 任务初始化完成后才能初始化。
一般的做法是使用有向无环图来组织任务的依赖关系,Android 已经有很多成熟的库:
- Google app-startup Android 官方的启动库,通过 ContentProvider 注册初始化/手动注册,只支持简单的依赖关系,缺少多线程支持,和相关回调。
- github.com/DSAppTeam/A…
- github.com/aiceking/Ap…
- github.com/johnsonlee/…
- 基于 booster 使用 asm 自动生成相关 task 依赖逻辑
在对 App 进行初始化优化时,我发现大部分的框架,对于初始化的配置有点繁琐,站在用户的角度来说,使用者关心的只有
- 如何组织任务的依赖关系(可以通过注解实现)
- 如何调用触发任务启动 (手动一行代码)
- 任务启动/结束的回调 (启动时传一个 callback)
- 任务在哪个线程运行 (协程负责)
于是我想到用注解(易用)+协程(管理多线程)的方式来写一个框架,在 github 无意间发现 github.com/wurensen/Ta… 这个项目,作者的实现思路非常好,于是 fork 此库实现了 initializer。
注解
注解的实现参考了 Room 和 johnsonlee/initializr
@Database(
entities = [DiyCloudConfiguration::class, GithubConfiguration::class, CodingConfiguration::class, GiteeConfiguration::class, UCloudConfiguration::class],
version = DB_CLOUD_VERSION,
exportSchema = true
)
abstract class CloudDataBase : RoomDatabase()
Room 通过 @Database 注解组织了当前数据库包含的表(entities)。
所以我们照猫画虎:
@Initialization(
tasks = [Task1::class,Task2::class,Task3::class,Task4::class])
abstract class AppInitializer : Initializer()
这样来表示一个初始化中包含的所有任务。
同样的 Task 的依赖关系也可以通过注解实现:
@Task(dependencies = [Task1::class])
class Task2 : InitializeTask(){
override suspend fun initialize(context: InitializeContext) {
withContext(Dispatchers.IO) {
delay(1000)
println("executed completely")
}
}
协程
Task 中的 initialize 方法是协程挂起方法,在这个方法自由选择切线程完成任务。
默认是通过 Dispathers.Main 启动,也通过 socpe 参数改变;通过 WithContext 自由切换。至于线程的优先级,则完全可以通过自定义 Dispather 来自定义。这部分属于线程管理,初始化框架按理也不需要管这些。
启动
initializer 通过反射(从易用性来说,这点性能可以忽略不计)创建 Initializer 实例:
// 创建初始化
val appInitializer = Initializer.Builder(AppInitializer::class.java).build()
// 开始启动任务
appInitializer.init(context = appContext, scope = launchScope, debug = true)
启动时的参数:
- context: Context
- scpoe: 协程启动运行的 scope
- debug: debug
debug 为 true 时会检查当前的任务是否是正确的有向无环图(无环),release 为了性能则不检查。
回调
每个任务开始执行和结束执行都会回调,方便做一些 hook 操作。
initializerA.init(this, debug = true, callback = object : Callback {
// 初始化开始启动(第一个任务开始启动)
override fun onInitializationStart(firstTask: InitializeTask) {
log("onInitializationStart, first is ${firstTask::class.qualifiedName}")
}
// 任务开始启动
override fun onTaskStart(task: InitializeTask) {
log("onTaskStart ${task::class.qualifiedName}, dependency ${task.dependencies.toList()}")
}
// 任务结束
override fun onTaskComplete(task: InitializeTask, timeConsuming: Long) {
log("onTaskComplete ${task::class.qualifiedName}, dependency ${task.dependencies.toList()}, timeConsuming = $timeConsuming ms")
}
// 全部初始化结束(最后一个任务结束)
override fun onInitializationComplete(
lastTask: InitializeTask,
totalTimeConsuming: Long
) {
log("onInitializationComplete, $totalTimeConsuming ms, lastTask is ${lastTask::class.qualifiedName}")
}
})