You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin协程中onAwait与await()的区别及Android实现方法

Kotlin协程中onAwait与await()的区别及Android场景下的正确用法

核心区别

  • await():这是一个挂起函数,调用后会直接暂停当前协程,直到对应的Deferred任务执行完成,返回任务的计算结果。如果任务执行时抛出异常,await()会重新抛出该异常,需要用try-catch处理。
  • onAwait:这是Deferred的一个属性,返回Job对象。它的作用是监听Deferred的完成事件,但不会暂停当前协程。你可以通过给它添加invokeOnCompletion回调,在任务完成(成功或失败)时触发逻辑,但它本身不返回任务结果,也不会阻塞协程流程。

你的代码问题分析

你写的代码里,async块内调用了viewModel.email.collect——如果email是StateFlow或SharedFlow,collect会一直挂起直到流被取消,而这类流通常不会主动结束。这就导致这个Deferred永远不会完成:

  • 调用resultEmail.await()会让当前协程永久挂起,永远拿不到结果;
  • resultEmail.onAwait的回调也永远不会触发。

Android中的正确实现方式

场景1:持续收集流的更新

如果需要监听email的所有更新,直接在协程里调用collect即可,不需要用async:

var value = ""
viewModelScope.launch {
    viewModel.email.collect { email ->
        value = email
        // 这里处理email的每次更新,比如更新UI
    }
}

场景2:获取流的单次最新值

如果只需要获取一次email的最新值,用first()(挂起函数,获取第一个发射的值)或者直接访问StateFlow的value属性(非挂起,仅适用于StateFlow):

var value = ""
viewModelScope.launch {
    // 方式1:挂起直到拿到第一个值(适用于所有Flow)
    val email = viewModel.email.first()
    value = email
    
    // 方式2:直接取StateFlow的最新值(非挂起,仅StateFlow可用)
    // value = viewModel.email.value
}

场景3:确实需要用Deferred的并行任务

如果是并行执行多个耗时任务(比如同时请求两个接口),才需要用到async+await/onAwait:

viewModelScope.launch {
    // 启动并行任务
    val emailDeferred = async { api.fetchUserEmail() }
    val nameDeferred = async { api.fetchUserName() }
    
    // 用await()等待结果,拿到后继续逻辑
    val email = emailDeferred.await()
    val name = nameDeferred.await()
    // 处理拿到的email和name
    
    // 用onAwait监听任务完成事件,不阻塞当前协程
    emailDeferred.onAwait.invokeOnCompletion { throwable ->
        if (throwable == null) {
            Log.d("TAG", "Email请求成功:${emailDeferred.getCompleted()}")
        } else {
            Log.e("TAG", "Email请求失败", throwable)
        }
    }
}

正确使用场景总结

  • 当你需要等待任务结果,并且要基于结果继续后续逻辑时,用await();
  • 当你不需要等待结果,只是想在任务完成时执行一些收尾逻辑(比如日志、状态上报),且不想阻塞当前协程时,用onAwait配合invokeOnCompletion。

内容的提问来源于stack exchange,提问作者Riezki Maisyar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 02:52:27