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”对应的链接)的结果,请问问题出在哪里?如何修复代码?
问题原因
- 同步循环覆盖请求:
forEach循环会在极短时间内连续调用loadUrl,WebView的加载请求是异步的,后发起的请求会直接覆盖前面的未完成请求,最终只处理最后一个URL。 - 错误的等待逻辑:
GlobalScope.launch里的delay(5000)只是等待5秒后一次性触发所有加载,没有针对每个页面的加载完成做等待,无法实现依次加载的效果。 - 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
相关产品推荐
相关产品推荐

