# startup-coroutine **Repository Path**: lotee/startup-coroutine ## Basic Information - **Project Name**: startup-coroutine - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-26 - **Last Updated**: 2026-02-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

Startup-Coroutine

一个基于 Kotlin 协程的 Android 启动框架,优雅地管理您的应用初始化流程。
探索特性 »

English · 报告 Bug · 提出新特性

*** `startup-coroutine` 是一个为 Android 设计的、基于 Kotlin 协程的异步启动框架。它通过拓扑排序智能地管理复杂的初始化依赖关系,并利用协程的强大能力实现任务的并行化,从而显著缩短应用的启动时间。框架设计精良,具备高级错误处理和生命周期管理能力,让您的应用初始化流程更健壮、更高效、更易于维护。 ## 📖 目录 * [✨ 核心特性](#-核心特性) * [📥 下载与集成](#-下载与集成) * [第一步:添加 JitPack 仓库](#第一步添加-jitpack-仓库) * [第二步:添加依赖](#第二步添加依赖) * [🚀 快速上手](#-快速上手) * [第一步:定义初始化任务](#第一步定义初始化任务) * [第二步:配置并启动框架](#第二步配置并启动框架) * [第三步:监听启动结果](#第三步监听启动结果) * [🧩 核心 API 解析](#-核心-api-解析) * [`Initializer`](#initializert) * [`Startup.Builder`](#startupbuilder) * [`StartupDispatchers`](#startupdispatchers) * [`DependenciesProvider`](#dependenciesprovider) * [🔧 高级用法](#-高级用法) * [封装实践](#封装实践) * [混淆规则](#混淆规则) * [异常处理机制](#异常处理机制) * [循环依赖检测](#循环依赖检测) * [🆚 与 Jetpack App Startup 对比](#-与-Jetpack-App-Startup-对比) * [🤝 贡献指南](#-贡献指南) * [📄 许可证](#-许可证) ## ✨ 核心特性 * **🔗 依赖管理**: 自动解析并按拓扑顺序执行任务,精确处理任务间的依赖关系。 * **⚡ 协程优先**: 原生支持 `suspend` 函数,轻松处理异步初始化(如网络请求、数据库迁移)。 * **🧵 灵活调度**: 提供多种线程调度策略(全主线程、全IO线程、IO执行主线程回调等),适应不同场景。 * **🚀 极致性能**: 框架自身的拓扑排序与调度逻辑在后台执行,对主线程几乎零干扰。 * **🛡️ 异常隔离**: 采用 `supervisorScope` 隔离并行任务,确保单个任务的失败不会导致整个启动流程崩溃。 * **👀 生命周期感知**: 通过 `LiveData` 观察启动结果,完美适配 Activity/Fragment 生命周期。 * **🌍 支持多进程**: 可配置初始化任务是否在多进程中执行,并自动过滤,完美适配复杂的应用架构。 * **🤚 可取消**: 返回标准协程 `Job`,支持随时安全地取消整个启动流程。 ## 📥 下载与集成 ### 第一步:添加 JitPack 仓库 在您的根项目 `settings.gradle.kts` (或 `settings.gradle`) 文件中,添加 JitPack 仓库地址。 ```kotlin // settings.gradle.kts dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() maven { setUrl("https://jitpack.io") } // <-- 添加这一行 } } ``` ### 第二步:添加依赖 在您需要使用此框架的模块(通常是 `app` 模块)的 `build.gradle.kts` 文件中,添加依赖项。请将 `Tag` 替换为最新的版本号。 ```kotlin // app/build.gradle.kts dependencies { // ... 其他依赖 implementation("com.github.Dboy233:startup-coroutine:Tag") } ``` 您可以通过上方的版本角标查看最新的版本号。 ## 🚀 快速上手 ### 第一步:定义初始化任务 每个初始化单元都需要实现 `Initializer` 接口。 * **`init(application, provider)`**: 包含实际的初始化逻辑。这是一个 `suspend` 函数。 * **`dependencies()`**: (可选) 声明当前任务所依赖的其他 `Initializer` 类。 **示例:定义两个任务** 一个用于初始化网络库的任务(`NetworkInitializer`),以及一个依赖于它的 API 服务初始化任务(`ApiServiceInitializer`)。 ```kotlin // 1. 定义一个产出 Retrofit 实例的任务 class NetworkInitializer : Initializer { override suspend fun init(application: Application, provider: DependenciesProvider): Retrofit { // 这是一个 suspend 函数,适合执行耗时操作 // 注意:默认情况下 init 在主线程被调用(取决于 Dispatchers 配置), // 如果有繁重 I/O,建议使用 withContext(Dispatchers.IO) 或配置 StartupDispatchers.ExecuteOnIO return Retrofit.Builder() .baseUrl("https://api.example.com") .build() } } // 2. 定义一个依赖于 NetworkInitializer 的任务 class ApiServiceInitializer : Initializer { // 声明依赖关系 override fun dependencies(): List>> { return listOf(NetworkInitializer::class) } override suspend fun init(application: Application, provider: DependenciesProvider): MyApiService { // 获取依赖项的结果。如果依赖项失败,ApiServiceInitializer 不会执行init val retrofit = provider.result(NetworkInitializer::class) return retrofit.create(MyApiService::class.java) } } ``` ### 第二步:配置并启动框架 在您的 `Application` 类中,使用 `Startup.Builder` 构建并启动框架。 ```kotlin class MyApplication : Application() { override fun onCreate() { super.onCreate() val startup = Startup.Builder(this) .add(NetworkInitializer()) // 添加任务 .add(ApiServiceInitializer()) // 添加任务 .setDispatchers(StartupDispatchers.ExecuteOnIO) // 设置线程策略:在IO线程初始化执行,主线程创建框架 .setDebug(true) // 开启调试模式,输出详细日志 .build() // 启动初始化流程。此调用是非阻塞的,会立即返回一个 Job。 startup.start() } } ``` ### 第三步:监听启动结果 框架提供了基于 `LiveData` 的结果观察机制。您可以在 `SplashActivity` 或 `MainActivity` 中监听启动是否完成。 ```kotlin class SplashActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 观察启动结果 Startup.observe(this) { result -> when (result) { is StartupResult.Success -> { Log.d("Startup", "🎉 所有任务完成!") goToMainActivity() } is StartupResult.Failure -> { Log.e("Startup", "🔥 启动失败: ${result.exceptions.size} 个错误") // 处理错误,例如弹窗提示或重试 } StartupResult.Idle -> { // 尚未开始或已重置 } } } } } ``` ## 🧩 核心 API 解析 ### `Initializer` 核心接口,定义一个初始化单元。 * `suspend fun init(application: Application, provider: DependenciesProvider): T`: 执行初始化逻辑。 * `fun dependencies(): List>>`: 返回依赖的任务列表。 * `fun isMultiProcess(): Boolean`: (可选) 声明该任务是否支持在非主进程中运行,默认为 `false`。 ### `Startup.Builder` 用于构建 `Startup` 实例的建造者。 * `add(Initializer<*>)`: 添加单个或多个任务。 * `setDispatchers(StartupDispatchers)`: 配置线程调度策略。 * `setDebug(Boolean)`: 是否输出调试日志(包含耗时统计和依赖图)。 * `build()`: 创建 `Startup` 实例。 ### `StartupDispatchers` 预置的线程调度策略,控制任务在哪个线程执行以及在哪个线程启动。 | 策略 | 说明 | 适用场景 | | :---------------- | :-------------------------------------- | :-------------------- | | **`Default`** | **(推荐)** 启动/排序在 IO 线程,`init` 在 **主线程**。 | 大多数包含 UI 初始化的场景。 | | **`ExecuteOnIO`** | 启动/排序在主线程,`init` 在 **IO 线程**。 | 任务主要是耗时 I/O (数据库、网络)。 | | **`AllIO`** | 全流程都在 IO 线程。 | 完全无 UI 操作的后台初始化。 | | **`AllMain`** | 全流程都在主线程。 | 仅适用于极轻量级的任务集合。 | ### `DependenciesProvider` 传递给 `init` 方法的参数,用于获取上游依赖的结果。 * `result(class)`: 获取结果,如果不存在或类型不匹配抛出异常。 * `resultOrNull(class)`: 安全获取结果,失败返回 null。 ## 🔧 高级用法 ### 封装实践 1. [`App.kt`](app/src/main/java/com/dboy/coroutine/App.kt) 2. [`BaseActivity.kt`](app/src/main/java/com/dboy/coroutine/BaseActivity.kt) 3. [`SplashActivity.kt`](app/src/main/java/com/dboy/coroutine/SplashActivity.kt) ### 混淆规则 ```text # 1. 保护 Initializer 接口本身不被移除或混淆 -keep class com.dboy.startup.coroutine.api.Initializer # 2. 关键规则: # 保持所有实现了 Initializer 接口的类的类名不被混淆。 # 同时保留无参构造函数(框架实例化时需要)。 # 这可以防止 R8 将不同的 Initializer 类合并,从而避免循环依赖报错。 -keep class * implements com.dboy.startup.coroutine.api.Initializer { (); } ``` ### 异常处理机制 框架会收集所有并行任务中的异常。 * 如果发生异常,`Startup.observe` 会收到 `StartupResult.Failure`。 * `Failure` 对象包含一个 `exceptions` 列表,您可以遍历它查看具体的错误原因。 * 使用 `setDebug(true)` 可以在 Logcat 中看到详细的错误堆栈和对应的任务名称。 ### 循环依赖检测 ### 多进程支持 从 `0.2.2-beta` 版本开始,框架原生支持多进程初始化。框架会自动检测当前进程,并只执行那些被允许在当前进程运行的任务。 #### 1. 声明多进程任务 让一个 `Initializer` 支持在多进程中运行,只需重写 `isMultiProcess()` 方法并返回 `true`。 ```kotlin class MyMultiProcessInitializer : Initializer { override suspend fun init(application: Application, provider: DependenciesProvider) { // ... 初始化逻辑 } // 重写此方法,声明支持多进程 override fun isMultiProcess(): Boolean = true } ``` **规则**:在非主进程中,只有 `isMultiProcess()` 返回 `true` 的任务才会被执行。如果一个任务依赖于另一个不支持多进程的任务,那么在子进程中,这个任务及其依赖链都将因依赖检查失败而被安全地中断。 #### 2. 处理第三方SDK进程(重要) 很多广告、推送SDK会创建自己的私有进程。这些进程生命周期短暂且行为不可控,我们不希望在其中运行任何我们自己的初始化逻辑。最佳实践是在 `Application.onCreate` 的入口处进行“进程过滤”,提前返回。 ```kotlin // In Application.onCreate() val currentProcessName = getCurrentProcessName() ?: "" val isMainProcess = currentProcessName == packageName // 如果既不是主进程,也不是我们明确允许的子进程(如 :webview),则直接返回 if (!isMainProcess && !isOurWhitelistedProcess(currentProcessName)) { return } // ... 后续才是 startup-coroutine 的构建和启动逻辑 ``` #### 3. 关于多进程数据共享 请注意,标准的 `SharedPreferences` **不是进程安全的**。如果在多个进程中依赖它共享数据,将导致数据错乱。推荐使用专为多进程设计的存储方案,如 `ContentProvider` 或腾讯的 `MMKV`。 ## 🆚 与 Jetpack App Startup 对比 在 `build()` 之后,调用 `start()` 时,框架会自动执行拓扑排序。如果检测到循环依赖(例如 A 依赖 B,B 依赖 A),会立即抛出 `IllegalStateException`,帮助您在开发阶段发现结构问题。 ## 🆚 与 Jetpack App Startup 对比 | 特性 | Jetpack App Startup | startup-coroutine | 优势说明 | | :------- | :--------------------- | :----------------------- | :------------------------------------------------------------------------------------------- | | **异步能力** | 不支持 (同步阻塞) | **原生支持协程** | **startup-coroutine** 的 `init` 是 `suspend` 函数,天然适配现代 Android 开发 (Room, Retrofit, DataStore)。 | | **线程控制** | 默认主线程 | **高度可配置** | 可一键切换全 IO 线程执行,避免 ANR。 | | **依赖参数** | 无 (通过 ContentProvider) | **DependenciesProvider** | 支持上游任务向下游传递初始化结果(如 OkHttp 实例传给 Retrofit)。 | | **结果监听** | 较弱 | **LiveData 观察** | 方便与 UI 生命周期绑定,制作启动页更简单。 | | **手动控制** | 支持 | **Builder 模式** | 更符合直觉的配置方式,支持懒加载和按需启动。 | ## 🤝 贡献指南 欢迎各种形式的贡献! 1. Fork 本仓库 2. 创建您的特性分支 (`git checkout -b feature/AmazingFeature`) 3. 提交您的更改 (`git commit -m 'Add some AmazingFeature'`) 4. 推送到分支 (`git push origin feature/AmazingFeature`) 5. 创建一个 Pull Request ## 📄 许可证 本项目采用 Apache 2.0 许可证。详情请参阅 [LICENSE](blob/LICENSE) 文件。