其他
Kuikly 异步与多线程编程:选择协程方案并安全切回…
在 Kuikly 项目中执行异步任务、切换线程、使用协程、回到 Kuikly 线程更新 UI 或排查线程安全问题时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 58/100 ×0.15
适用场景
Kuikly 异步与多线程编程:选择协程特定
解决思路
- 遵守 Kuikly 线程约束:所有 Kuikly UI 操作(View、Attr、Event、observable、Module 方法、setTimeout 等)只能在 Kuikly 线程调用,因为 Kuikly UI 相关类非线程安全。
- 异步任务完成后必须回到 Kuikly 线程,才能更新 UI 或访问响应式属性。
- 在动态化场景中不要使用 kotlinx 协程(js 目标平台不支持多线程),只能使用 Module 机制或 Kuikly 内建协程。
- 根据动态化支持、依赖增量、线程安全选择协程实现方式:回调(无协程)支持动态化、无依赖增量、不涉及线程安全;Kuikly 内建协程支持动态化、无依赖增量、自动保障线程安全;kotlinx 协程不支持动态化、增加 kotlinx 协程库依赖、需要自行考虑线程安全。
- 简单异步优先使用 Kuikly 内建协程:框架自带,始终在 Kuikly 线程执行,无线程切换开销,支持动态化。
- 使用 Kuikly 内建协程的 API 入口:`GlobalScope.launch { ... }`(全局作用域);`lifecycleScope.launch { ... }`(绑定 Pager 生命周期,推荐);`async { ... }` / `await()`(并发获取结果)。
- 导入 Kuikly 内建协程:`import com.tencent.kuikly.core.coroutines.GlobalScope`、`import com.tencent.kuikly.core.coroutines.launch`、`import com.tencent.kuikly.core.coroutines.async`、`import com.tencent.kuikly.core.coroutines.delay`。
- 注意:Kuikly 内建协程 API 本身非线程安全,不能在 Kuikly 线程外调用。
- 需要多线程且不需要动态化时,接入 kotlinx.coroutines 库:Kotlin 官方协程库,支持多线程调度器(Dispatchers.Default/IO/Main 等),不支持动态化。
- 添加 kotlinx.coroutines 依赖:iOS & Android 使用 `implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$KOTLINX_COROUTINES_VERSION")`;鸿蒙使用 `implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$KOTLINX_COROUTINES_OHOS_VERSION")`。
- 需要从非 Kuikly 线程切回 Kuikly 线程时,接入 kuiklyx.coroutines 库,使用其 `Dispatchers.Kuikly` 调度器和 `KuiklyContextScheduler` 回调 API。
- 添加 kuiklyx.coroutines 依赖:iOS & Android 使用 `implementation("com.tencent.kuiklyx:coroutines:$KUIKLYX_COROUTINES_VERSION")`;鸿蒙使用 `implementation("com.tencent.kuiklyx:coroutines:$KUIKLYX_COROUTINES_OHOS_VERSION")`。
- 使用 kuiklyx 协程方式 API:启动协程在 Kuikly 线程执行:`GlobalScope.launch(Dispatchers.Kuikly[ctx]) { ... }`;在协程中切换到 Kuikly 线程:`withContext(Dispatchers.Kuikly[ctx]) { ... }`。
- 使用 kuiklyx 回调方式 API:`KuiklyContextScheduler.runOnKuiklyThread(pagerId) { cancel -> if (cancel) return; // 在 Kuikly 线程执行 }`。
- 按场景选择异步方式:只需简化回调且无多线程诉求,选择 Kuikly 内建协程;需要执行耗时任务且支持动态化,选择 Module 机制(可配合内建协程);需要多线程且不需要动态化,选择 kotlinx 协程 + kuiklyx 协程;Compose DSL 页面,选择 `LaunchedEffect + withContext`。
- 遵循一致性原则:选择方案时关注当前项目或模块已有的异步编程方式,优先保持一致,避免同一模块混用多套异步方案。
- 详细场景示例和代码参考 `SCENARIOS.md`。
- Compose DSL 页面(继承 `ComposeContainer`)使用 kotlinx 协程体系。
- 在 Compose 中使用 `LaunchedEffect(Unit)` 启动协程,默认在 Kuikly 线程执行(通过 `ComposeDispatcher` 调度)。
- 在 Compose 中执行耗时任务时,使用 `withContext(Dispatchers.IO) { fetchData() }` 切换到 IO 线程;`withContext` 返回后自动回到 Kuikly 线程。
- 在 Compose 中更新 State 前确保已回到默认调度器(Kuikly 线程)。
- `viewModelScope` 绑定到 Kuikly 线程,ViewModel 销毁时自动取消。
- 跨平台定义 `Dispatchers.IO`:在 commonMain 中声明 `internal expect val Dispatchers.IO: CoroutineDispatcher`;在 androidMain / appleMain / ohosArm64Main 中 actual 使用平台原生 IO 调度器;在 jsMain(不支持多线程)中 actual 使用 `Dispatchers.Default`。
- 遵守线程安全规则:Kuikly UI 相关类(View、Attr、Event、ObservableProperties、GlobalFunctions、Module 方法、Layout 等)非线程安全,只能在 Kuikly 线程访问。
- 开启线程安全验证:在 `override fun willInit()` 中调用 `Pager.VERIFY_THREAD = true`、`Pager.VERIFY_REACTIVE_OBSERVER = true`,并通过 `Pager.verifyFailed { exception -> println("线程安全验证失败: ${exception.message}"); throw exception }` 自定义验证失败处理。
- 详细线程安全用法和示例参考 `THREAD_SAFETY.md`。
- 避免在非 Kuikly 线程直接更新 observable;应通过 `Dispatchers.Kuikly` 或 `KuiklyContextScheduler` 切回 Kuikly 线程。
- 避免在非 Kuikly 线程调用 Module 方法;Module 的 `acquireModule` / `toNative` 等方法需在 Kuikly 线程调用。
- 避免在动态化场景使用 kotlinx 协程;应使用 Kuikly 内建协程或 Module 机制。
- 避免在 Kuikly 线程外调用内建协程 API;内建协程 API 只能在 Kuikly 线程调用。
- 处理 Pager 销毁后的回调时,在 `KuiklyContextScheduler` 回调中检查 `cancel` 参数。
- 不要在 `verifyFailed` 回调中操作 UI,因为验证失败通常发生在非 Kuikly 线程,不能调用 UI API。
- Compose 中避免在 IO 线程更新 State;应使用 `withContext` 回到默认调度器后再更新 State。
适用边界 · 注意事项
- 非 Kuikly 项目或未使用 Kuikly 框架的 Kotlin 项目。
- 没有异步/多线程需求,仅执行同步任务时不必引入协程。
- 需要动态化支持时,不要采用 kotlinx 协程方案(应改用内建协程或 Module 机制)。