prasad-vennam/awesome-android-ai-agent-skills

android-coroutines-expert

Use to enforce safe concurrency, correct Dispatcher usage, and proper Channel vs StateFlow patterns in ViewModels.

查看源码

使用方法

  1. 复制安装命令,在自己的智能体环境安装前先检查源码包。
  2. 从原始文档核对所需工具、凭据和支持的宿主。
  3. 说明输入材料与期望交付物,并对照来源检查输出。
npx skills add https://github.com/prasad-vennam/awesome-android-ai-agent-skills --skill android-coroutines-expert

开始前需了解

  • 安装不包含模型订阅、API 额度或访问文件的权限。
  • 仓库星数和安装量反映活跃情况,不等于独立质量或安全测试。
仓库原始内容

按源仓库内容呈现,保留标题、案例、代码、表格、链接以及原文引用的演示图片。

Coroutines & Concurrency Mastery ⚡🧵

A strict rulebook to prevent thread-blocking, memory leaks, and lost UI events in modern Android applications.

⚡ When to Use

  • ViewModel Logic: Launching coroutines for network/database requests.
  • One-Time UI Events: Showing Snackbars, Toasts, or Navigation triggers.
  • Parallel Work: Running multiple non-blocking tasks.

🚦 Rule 1: The UI Event Dilemma (StateFlow vs Channel)

You must explicitly distinguish between UI State (things that persist on rotation) and UI Events (things that happen once, like a Toast or Navigation).

  • UI STATE: Use MutableStateFlow.
  • UI EVENTS: Use an un-buffered Channel exported as a Flow. NEVER use SharedFlow with replay = 0 or MutableStateFlow for one-time events, because if the app rotates, the event might be dropped or replayed twice.

The Golden Implementation:

kotlin
class MyViewModel : ViewModel() {
    // 1. UI STATE
    private val _uiState = MutableStateFlow(MyState())
    val uiState = _uiState.asStateFlow()

    // 2. ONE-TIME EVENTS
    private val _uiEvent = Channel<MyAction>()
    val uiEvent = _uiEvent.receiveAsFlow()

    fun triggerSnackbar() {
        viewModelScope.launch {
             _uiEvent.send(MyAction.ShowSnackbar)
        }
    }
}

🚥 Rule 2: Dispatcher Discipline

Agents frequently launch heavy database or network calls on the default dispatcher (Dispatchers.Main inside a viewModelScope.launch).

  • Rule: If you are using Retrofit or Room, they are naturally "main-safe", so viewModelScope.launch { } is fine.
  • Rule: If you are doing manual file I/O, heavy JSON parsing, or bitmap manipulation, you MUST switch to Dispatchers.IO using withContext(Dispatchers.IO) { ... }.
  • Rule: If you are doing CPU-heavy sorting or filtering on massive lists, use Dispatchers.Default.

🛑 Rule 3: Structured Concurrency

If an agent executes multiple independent API requests inside a viewModelScope.launch, and one fails, it cancels the entire scope/parent job!

The Anti-Pattern:

kotlin
viewModelScope.launch {
    // If ApiA fails, ApiB is cancelled!
    val resultA = apiA.fetch() 
    val resultB = apiB.fetch()
}

The Architect's Standard (supervisorScope or async):

kotlin
viewModelScope.launch {
    // Both attempt to run. If A fails, B continues successfully.
    supervisorScope {
        val deferredA = async { apiA.fetch() }
        val deferredB = async { apiB.fetch() }
        
        try { val a = deferredA.await() } catch (e: Exception) {}
        try { val b = deferredB.await() } catch (e: Exception) {}
    }
}

🔋 Rule 4: collectAsStateWithLifecycle

As enforced in our Code Review checklists, NEVER use collectAsState() in Compose UI. Always use collectAsStateWithLifecycle() to ensure Coroutines pause fetching when the screen goes to the background.

按任务相关推荐

来自同一仓库

更多 Skills

全部 Skills