webView 的canGoBack/goBack 回退栈
使用
        // 系统返回键onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {override fun handleOnBackPressed() {if (dwebView?.canGoBack() == true) dwebView?.goBack()else {isEnabled = falseonBackPressedDispatcher.onBackPressed()isEnabled = true}}})
这样就可以了 ✅
但要实现"真正的回退功能",还需要注意几个关键点:
历史栈构建要点
- 必须确保历史栈能正常生成
 shouldOverrideUrlLoading方法中对http/https请求要返回false,否则无法记录历史,导致canGoBack()始终为false- 遇到 
target="_blank"或window.open的页面,需要在WebChromeClient.onCreateWindow中将新窗口 URL 重定向到当前 WebView,否则不会生成历史记录 
返回键处理的优化建议
- 在 Activity 中,"没有历史"时直接调用 
finish()即可 - 使用 
dispatcher.onBackPressed()递归处理也可以,但finish()更直观 
推荐实现代码
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {override fun handleOnBackPressed() {val wv = dwebViewif (wv != null && wv.canGoBack()) {wv.goBack()} else {// Activity 处理finish()// Fragment 处理// findNavController().popBackStack() 或 parentFragmentManager.popBackStack()}}
})
常见问题排查
- 前端是 SPA 应用且使用了 
history.replaceState(不增加历史记录)导致回退失效 - 需要与前端协调 - 拦截了 
http/https请求并返回true自行处理加载 - 历史记录不会增加 - 未处理 
target="_blank"- 历史记录不增加 - 错误页面/重定向导致停留在同一页面(可在 
onReceivedError中跳转自定义错误页并允许后退) 
Fragment 使用注意
- 使用 
addCallback(viewLifecycleOwner, ...)绑定到视图生命周期,防止内存泄漏 - 没有历史记录时使用 
popBackStack(),不要调用finish() 
X5(TBS)内核适配
只需将类名替换为 com.tencent.smtt.sdk.*,逻辑完全一致
总结
基础框架"canGoBack → goBack;否则执行系统返回"的思路是正确的。只需处理好"同页打开链接"和"新窗口重定向到当前页"这两点,回退功能就能稳定工作。
