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

Android WebView列表迭代异常:仅加载最后一项如何解决?

问题描述

我有一个URL列表,想要遍历列表依次加载每个URL,但迭代失败,仅加载了列表的最后一项。

WebView启动时初始加载的URL代码:

webView.loadUrl("https://translate.google.com/?sl=$from&tl=$into&text=Hello&op=translate")

URL列表定义:

val items = listOf(
    "https://translate.google.com/?sl=$from&tl=$into&text=First text&op=translate",
    "https://translate.google.com/?sl=$from&tl=$into&text=Second text&op=translate",
    "https://translate.google.com/?sl=$from&tl=$into&text=Third text&op=translate"
)

页面加载完成后遍历加载的代码:

webView.webViewClient = object : WebViewClient() {
    override fun onPageFinished(view: WebView?, url: String?) {
        super.onPageFinished(view, url)
        GlobalScope.launch {
            delay(5000)
            withContext(Dispatchers.Main) {
                items.forEach {
                    view?.loadUrl(it)
                    injectJavascript(view)
                }
            }
        }
    }
}

最终仅得到最后一个URL(“Third text”对应的链接)的结果,请问问题出在哪里?如何修复代码?

问题原因
  1. 同步循环覆盖请求:forEach循环会在极短时间内连续调用loadUrl,WebView的加载请求是异步的,后发起的请求会直接覆盖前面的未完成请求,最终只处理最后一个URL。
  2. 错误的等待逻辑:GlobalScope.launch里的delay(5000)只是等待5秒后一次性触发所有加载,没有针对每个页面的加载完成做等待,无法实现依次加载的效果。
  3. GlobalScope风险:使用GlobalScope会导致协程生命周期不受控,可能引发内存泄漏或意外行为。
修复方案

我们需要维护一个当前加载的索引,每次页面加载完成后,加载列表中的下一个URL,直到所有URL处理完毕。同时使用与页面生命周期绑定的协程作用域(如lifecycleScope)替代GlobalScope:

// 定义当前加载的索引,初始值为0
private var currentItemIndex = 0

// 初始化WebView
webView.webViewClient = object : WebViewClient() {
    override fun onPageFinished(view: WebView?, url: String?) {
        super.onPageFinished(view, url)
        
        // 跳过初始页面的处理(如果初始URL不在items列表中)
        if (url == "https://translate.google.com/?sl=$from&tl=$into&text=Hello&op=translate") {
            lifecycleScope.launch {
                delay(5000)
                loadNextItem(view)
            }
            return
        }
        
        // 处理当前页面的JS注入
        injectJavascript(view)
        
        // 延迟后加载下一个项(根据需要调整延迟时间)
        lifecycleScope.launch {
            delay(5000)
            loadNextItem(view)
        }
    }
}

// 加载下一个URL的方法
private fun loadNextItem(view: WebView?) {
    if (currentItemIndex < items.size) {
        view?.loadUrl(items[currentItemIndex])
        currentItemIndex++
    }
}

关键调整说明:

  • 索引追踪:用currentItemIndex记录当前加载的位置,每次加载完成后递增,确保逐个处理列表项。
  • 生命周期绑定协程:使用lifecycleScope(需要依赖androidx.lifecycle:lifecycle-runtime-ktx库)替代GlobalScope,保证协程随页面生命周期销毁,避免内存泄漏。
  • 分阶段处理:区分初始页面和列表项页面的加载完成逻辑,确保初始页面加载完成后才开始遍历列表。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 10:12:38