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

网页加载完成后取消协程超时任务仍打日志,如何解决?

解决协程取消后仍输出超时日志的问题

问题原因

原代码在onPageFinished里通过launch调用cancelAndJoin(),会导致取消动作存在延迟。如果页面加载完成时,delay(5000)已经执行完毕,协程会跳过ensureActive()检查(此时协程仍处于活跃状态),直接输出超时日志,之后才完成取消操作,从而出现不符合预期的日志输出。

修复方案

1. 简化协程取消逻辑

在onPageFinished中直接调用cancel()(无需用launch包裹,也不需要cancelAndJoin()),因为cancel()是同步操作,会立即标记协程为取消状态,打断正在执行的delay:

override fun onPageFinished(view: WebView?, url: String?) {
    super.onPageFinished(view, url)
    logUtil.i(TAG, "Finished loading $url")
    // 直接取消协程,无需在新协程中执行
    loadTimer?.cancel()
}

2. 移除冗余的ensureActive()

delay()本身是可取消的挂起函数,当协程被取消时,delay()会立即抛出CancellationException终止协程,不会执行后续的日志代码。因此ensureActive()是多余的,可以移除:

override fun onStart() {
    super.onStart()

    loadTimer = launch {
        delay(TimeUnit.SECONDS.toMillis(5))
        // 仅当协程未被取消(即超时)时才执行日志
        logUtil.w(TAG, "Loading took longer than expected")
    }

    webView.loadUrl(url)
}

3. 完善生命周期清理

为避免页面销毁后协程仍运行,建议在onDestroy中也取消协程:

override fun onDestroy() {
    super.onDestroy()
    loadTimer?.cancel()
}

修复后逻辑

  • 若页面在5秒内加载完成,cancel()会立即打断delay(),协程终止,不会输出超时日志。
  • 若页面加载超过5秒,delay()执行完毕后输出超时日志。
  • 页面销毁时主动取消协程,避免内存泄漏和无效日志。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 18:05:18