suspendCancellableCoroutine 和 withTimeoutOrNull 的协同工作机制

1. 核心机制
  • suspendCancellableCoroutine
    提供可取消的挂起协程能力,通过 continuation.invokeOnCancellation 注册取消时的清理逻辑。当外部触发取消(如超时、父协程取消)时,自动执行清理并抛出 CancellationException

  • withTimeoutOrNull
    在指定超时时间(如 2000ms)后,若协程未完成,会发送取消信号。与 suspendCancellableCoroutine 配合时,能立即终止挂起状态。

2. 最佳实践模板
suspend fun executeWithTimeout(): ResultType? {
    return withTimeoutOrNull(TIMEOUT_MS) {
        suspendCancellableCoroutine { cont ->
            val listener = createListener { result ->
                if (cont.isActive) cont.resume(result)
            }

            cont.invokeOnCancellation {
                removeListener(listener) // 清理资源
            }

            registerListener(listener) // 启动异步操作
        }
    }
}
3. 工作流程(含超时场景)
withTimeoutOrNull(3000) { // 3秒超时控制
    suspendCancellableCoroutine { continuation ->
        // 注册取消时的资源清理
        continuation.invokeOnCancellation { 
            unregisterListener(listener) // 关键:防止泄漏
        }

        // 异步操作(例如关闭WiFi)
        registerListener(listener)
        closeWifi()

        // 成功回调(正常情况)
        fun onSuccess() {
            continuation.resume(true) // 手动恢复协程
        }
    }
} ?: run {
    Log.d(TAG, "超时啦")
    false // 超时返回null,通过Elvis运算符转为false
}
4. 超时触发的详细时序
时间轴事件结果
T=0ms进入 withTimeoutOrNull 块开始计时
T=0ms调用 suspendCancellableCoroutine挂起协程
T<2000ms收到 onStateChanged(WIFI_STATE_DISABLED)调用 resume(true),协程完成
T≥2000ms未收到回调,超时触发执行 invokeOnCancellation,返回 null
任何时刻父协程取消同超时逻辑
5.为什么用suspendCancellableCoroutine,suspendCoroutine不行?

根本原因在于:

  • suspendCancellableCoroutine 支持外部取消(如 withTimeout 超时、父协程取消),而 suspendCoroutine 不支持。

suspendCancellableCoroutine 

  • 自动响应取消:当外部触发超时(如 withTimeout)或协程被取消时,suspendCancellableCoroutine 会立即执行 invokeOnCancellation 回调,并抛出 CancellationException,从而结束挂起状态

suspendCoroutine 

  • 不支持取消:即使外部调用 withTimeoutsuspendCoroutine 仍会继续挂起,直到手动调用 continuation.resume()

  • 超时失效withTimeout 试图取消协程,但 suspendCoroutine 不会响应取消请求,导致协程永远挂起,超时机制失效。

特性suspendCancellableCoroutinesuspendCoroutine
是否支持取消✅ 是(自动响应 withTimeout❌ 否
超时是否生效✅ 是❌ 否
资源清理✅ 通过 invokeOnCancellation❌ 需手动处理
推荐使用场景所有需要超时/取消的挂起操作无需取消的简单场景
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值