mcpField
A
android-coroutines

android-coroutines

github.com/new-silvermoon开发992542 次安装13 周前更新
代码仓库

关于 android-coroutines

面向 Android Kotlin 开发者的协程实践技能,提供结构化并发、生命周期安全、错误处理和测试方面的规则与模式,适用于数据获取及后台处理等任务。

主要功能

  1. 01注入 CoroutineDispatcher
  2. 02安全收集 Flow
  3. 03使用 viewModelScope
  4. 04处理取消与异常
  5. 05用 callbackFlow 转换回调
  6. 06使用 runTest 测试

适用场景

  1. 01实现 API 或数据库数据获取
  2. 02将回调 API 转为 Flow
  3. 03避免生命周期相关的任务泄漏
  4. 04测试协程与 ViewModel

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/new-silvermoon/awesome-android-agent-skills --skill android-coroutines

安装后在 Claude Code 中输入/android-coroutines确认已加载。

详细介绍

Android Coroutines 专家技能

此技能提供在 Android 上编写生产级 Kotlin Coroutines 代码的权威规则和模式。它遵循结构化并发、生命周期安全及现代最佳实践(2025 年标准)。

职责

  • 异步逻辑:实现挂起函数、Dispatcher 管理和并行执行。
  • 响应式流:实现 Flow、StateFlow、SharedFlow 和 callbackFlow。
  • 生命周期集成:管理作用域(viewModelScope、lifecycleScope)和安全收集(repeatOnLifecycle)。
  • 错误处理:实现 CoroutineExceptionHandler、SupervisorJob 和合理的 try-catch 层级。
  • 可取消性:通过 ensureActive() 确保长时间运行的操作能够协作式取消。
  • 测试:配置 TestDispatcher 和 runTest。

适用场景

用户提出以下需求时启用此技能:

  • “从 API/数据库获取数据。”
  • “执行后台处理。”
  • “修复与线程/任务相关的内存泄漏。”
  • “将监听器/回调转换为 Coroutines。”
  • “实现 ViewModel。”
  • “处理 UI 状态更新。”

关键规则与限制

1. 注入 Dispatcher(可测试性)
  • 绝不在类中硬编码 Dispatcher(例如 Dispatchers.IO、Dispatchers.Default)。
  • 始终通过构造函数注入 CoroutineDispatcher。
  • 为方便起见,构造函数参数中默认使用 Dispatchers.IO,但要允许覆盖。
// CORRECT
class UserRepository(
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) { ... }

// INCORRECT
class UserRepository {
    fun getData() = withContext(Dispatchers.IO) { ... }
}
2. 主线程安全
  • Data 层或 Domain 层定义的所有挂起函数都必须是主线程安全的。
  • 一次性调用应以 suspend 函数形式提供。
  • 数据变更应以 Flow 形式提供。
  • 调用方(ViewModel)应能从 Dispatchers.Main 调用这些函数,而不会阻塞 UI。
  • 在 repository 实现中使用 withContext(dispatcher),将执行切换到后台。
3. 生命周期感知的收集
  • 绝不要直接在 lifecycleScope.launch 或 launchWhenStarted(已弃用/不安全)中收集 flow。
  • 在 Activity 或 Fragment 中收集 flow 时,始终使用 repeatOnLifecycle(Lifecycle.State.STARTED)。
// CORRECT
viewLifecycleOwner.lifecycleScope.launch {
    viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.uiState.collect { ... }
    }
}
4. 使用 ViewModel 作用域
  • 在 ViewModel 中使用 viewModelScope 启动协程。
  • 不要向 View 暴露 ViewModel 的挂起函数。ViewModel 应暴露 StateFlow 或 SharedFlow,供 View 观察。
5. 封装可变状态
  • 绝不公开暴露 MutableStateFlow 或 MutableSharedFlow。
  • 使用 .asStateFlow() 或向上转型,将它们作为只读 StateFlow 或 Flow 暴露。
6. 禁止使用 GlobalScope
  • 绝不使用 GlobalScope。它会破坏结构化并发并导致泄漏。
  • 如果任务必须在当前作用域结束后继续运行,请使用注入的 applicationScope(与 Application 生命周期绑定的自定义作用域)。
7. 异常处理
  • 绝不要在通用的 catch (e: Exception) 块中捕获 CancellationException,却不重新抛出。
  • 仅当明确重新抛出 CancellationException 时才使用 runCatching。
  • CoroutineExceptionHandler 仅用于顶层协程(launch 内)。它在 async 或子协程中不起作用。
8. 可取消性
  • 协程采用协作式取消。除非检查取消状态,否则它们不会立即停止。
  • 在紧密循环中(例如处理大型列表、读取文件),始终调用 ensureActive() 或 yield() 来检查是否已取消。
  • delay() 和 withContext() 等标准函数本身就支持取消。
9. 回调转换
  • 使用 callbackFlow 将基于回调的 API 转换为 Flow。
  • 在 callbackFlow 代码块末尾始终使用 awaitClose 注销监听器。

代码模式

使用 Flow 的 Repository 模式
class NewsRepository(
    private val remoteDataSource: NewsRemoteDataSource,
    private val externalScope: CoroutineScope, // For app-wide events
    private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) {
    val newsUpdates: Flow<List<News>> = flow {
        val news = remoteDataSource.fetchLatestNews()
        emit(news)
    }.flowOn(ioDispatcher) // Upstream executes on IO
}
并行执行
suspend fun loadDashboardData() = coroutineScope {
    val userDeferred = async { userRepo.getUser() }
    val feedDeferred = async { feedRepo.getFeed() }
    
    // Wait for both
    DashboardData(
        user = userDeferred.await(),
        feed = feedDeferred.await()
    )
}
使用 runTest 进行测试
@Test
fun testViewModel() = runTest {
    val testDispatcher = StandardTestDispatcher(testScheduler)
    val viewModel = MyViewModel(testDispatcher)
    
    viewModel.loadData()
    advanceUntilIdle() // Process coroutines
    
    assertEquals(expectedState, viewModel.uiState.value)
}

评论

支持 Markdown