WebView中通过NavController跳转Fragment崩溃问题求助
看起来你的Toast能正常显示,说明valid()方法确实被JS正确调用了,但点击确认按钮时崩溃,大概率是生命周期安全问题或者主线程调用问题导致的,下面我给你一步步分析和解决:
可能的崩溃原因
- JavascriptInterface方法运行在非主线程:WebView的JS接口方法默认在后台线程执行,虽然Toast有自动切换主线程的逻辑,但AlertDialog的点击回调里执行导航操作时,可能仍处于非主线程,触发Android的UI线程检查崩溃。
- NavController引用失效:你在
onViewCreated里获取的navController依赖于当前Fragment的View,当Fragment的View被销毁(比如用户返回、页面切换),但WebView还持有这个navController引用时,调用navigate就会崩溃。 - 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) } }
额外检查项
- 验证导航动作配置:打开你的导航图(
nav_graph.xml),确认是否存在action_landingPageCreditCardFragment_to_pesananFragment这个动作,并且目标Fragment是pesananFragment,动作ID完全匹配。 - 避免内存泄漏:记得在Fragment销毁时,清理WebView的JavascriptInterface引用,比如在
onDestroyView里调用binding.webViewCreditCard.removeJavascriptInterface("btn"),防止WebView持有Fragment的引用导致内存泄漏。
这样修改后,应该就能解决跳转崩溃的问题了。
内容的提问来源于stack exchange,提问作者Pif
相关产品推荐
相关产品推荐

