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

WebView中通过NavController跳转Fragment崩溃问题求助

解决WebView JavascriptInterface中NavController跳转崩溃的问题

看起来你的Toast能正常显示,说明valid()方法确实被JS正确调用了,但点击确认按钮时崩溃,大概率是生命周期安全问题或者主线程调用问题导致的,下面我给你一步步分析和解决:

可能的崩溃原因

  1. JavascriptInterface方法运行在非主线程:WebView的JS接口方法默认在后台线程执行,虽然Toast有自动切换主线程的逻辑,但AlertDialog的点击回调里执行导航操作时,可能仍处于非主线程,触发Android的UI线程检查崩溃。
  2. NavController引用失效:你在onViewCreated里获取的navController依赖于当前Fragment的View,当Fragment的View被销毁(比如用户返回、页面切换),但WebView还持有这个navController引用时,调用navigate就会崩溃。
  3. Fragment已脱离Activity:当Fragment不再附着到Activity时,调用requireContext()或者导航操作会抛出IllegalStateException。

修复方案

下面是修改后的代码,我标注了关键修复点:

class LandingPageCreditCardFragment : Fragment(R.layout.fragment_landing_page_credit_card) {
    private val binding by viewBinding(FragmentLandingPageCreditCardBinding::bind)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val url = requireArguments().getString("url")!!
        Log.i("link url", url)
        showWebViewContent(url)
    }

    private fun showWebViewContent(url: String) {
        binding.webViewCreditCard.settings.javaScriptEnabled = true
        binding.webViewCreditCard.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
                url?.let { view?.loadUrl(it) }
                return true
            }
        }

        binding.webViewCreditCard.addJavascriptInterface(object : Any() {
            @JavascriptInterface
            fun valid() {
                // 修复点1:强制切换到主线程执行所有UI和导航操作
                requireActivity().runOnUiThread {
                    // 修复点2:检查Fragment是否仍附着在Activity上
                    if (!isAdded) {
                        return@runOnUiThread
                    }

                    Toast.makeText(requireContext(), "test", Toast.LENGTH_SHORT).show()
                    val builder = AlertDialog.Builder(requireContext())
                    builder.setTitle("Konfirmasi")
                    builder.setMessage("navigasi ke pesanan")
                    builder.setPositiveButton("Ya") { dialog, which ->
                        // 修复点3:使用Fragment的findNavController()方法,而非持有View级别的引用
                        findNavController().navigate(R.id.action_landingPageCreditCardFragment_to_pesananFragment)
                        dialog.dismiss()
                    }
                    builder.setNegativeButton("Tidak") { dialog, which ->
                        dialog.dismiss()
                    }
                    builder.show()
                }
            }
        }, "btn")

        binding.webViewCreditCard.loadUrl(url)
    }
}

额外检查项

  1. 验证导航动作配置:打开你的导航图(nav_graph.xml),确认是否存在action_landingPageCreditCardFragment_to_pesananFragment这个动作,并且目标Fragment是pesananFragment,动作ID完全匹配。
  2. 避免内存泄漏:记得在Fragment销毁时,清理WebView的JavascriptInterface引用,比如在onDestroyView里调用binding.webViewCreditCard.removeJavascriptInterface("btn"),防止WebView持有Fragment的引用导致内存泄漏。

这样修改后,应该就能解决跳转崩溃的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:27:35