NullPointerException:createProgressDialog

NullPointerException: createProgressDialog

从 Crashlytics 获取 Android version: 10 的下一个错误:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
       at android.app.Dialog.<init>(Dialog.java:196)
       at android.app.ColorBaseAlertDialog.<init>(ColorBaseAlertDialog.java:33)
       at android.app.AlertDialog.<init>(AlertDialog.java:208)
       at android.app.AlertDialog.<init>(AlertDialog.java:204)
       at android.app.ProgressDialog.<init>(ProgressDialog.java:112)
       at com.sau.authenticator.widget.fragment.BaseFragment.createProgressDialog(BaseFragment.java:46)
       at com.sau.authenticator.widget.fragment.BaseFragment.showLoadProgress(BaseFragment.java:41)
       at com.sau.authenticator.widget.fragment.WebViewFragment$webViewClient.onPageStarted(WebViewFragment.java:69)
       at i6.c(i6.java:2)
       at Hn.handleMessage(Hn.java:145)
       at android.os.Handler.dispatchMessage(Handler.java:107)
       at android.os.Looper.loop(Looper.java:228)
       at android.app.ActivityThread.main(ActivityThread.java:7782)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:981)

在我的函数 createProgressDialog 中,它在 BaseFragment 中被调用:

abstract class BaseFragment : Fragment() {
    private var progressDialog: ProgressDialog? = null
    val activityComponents: ActivityComponentsContract?
        get() = activity?.activityComponentsContract

    override fun onDestroy() {
        progressDialog?.dismiss()
        progressDialog = null
        super.onDestroy()
    }

    protected fun showLoadProgress() {
        if (progressDialog == null) progressDialog = createProgressDialog()
        progressDialog?.show()
    }

    private fun createProgressDialog(): ProgressDialog? {
        val dialog = ProgressDialog(activity, R.style.ProgressDialogTheme)
        dialog.setCancelable(false)
        dialog.setProgressStyle(android.R.style.Widget_ProgressBar_Large)
        return dialog
    }

    protected fun dismissLoadProgress() {
        progressDialog?.dismiss()
    }
}

这是我的 WebViewFragment 的代码:

class WebViewFragment : BaseFragment() {

    private var url = ""
    private var title = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            url = it.getString(KEY_URL, "")
            title = it.getString(KEY_TITLE, "")
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        activityComponents?.updateAppbar(
            title = title,
            backActionImageResId = R.drawable.ic_appbar_action_back
        )
        return inflater.inflate(R.layout.fragment_web_view, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        customWebView?.webViewClient = webViewClient
        customWebView?.loadUrl(url)
    }

    private val webViewClient = object : WebViewClient() {

        override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
            super.onPageStarted(view, url, favicon)
            showLoadProgress()
        }

        override fun onPageFinished(view: WebView?, url: String?) {
            super.onPageFinished(view, url)
            dismissLoadProgress()
        }
    }

    companion object {
        const val KEY_URL = "KEY_URL"

        fun newBundle(url: String = "", title: String): Bundle {
            return Bundle().apply {
                putString(KEY_URL, url)
                putString(KEY_TITLE, title)
            }
        }
    }
}

我不太熟悉 WebView,但似乎在调用 onPageStarted() 时您的用户已经导航离开(或旋转他的设备)。因此,您的 FragmentonDestroyView() 可能已经被调用,但您没有通知您的 WebView 开始加载您的 url。这就是为什么 activitynull 而你得到异常。

因此,在您的 WebViewFragment 的生命周期回调中,确保您也通知了您的 WebView

override fun onResume() {
    super.onResume()
    customWebView?.onResume()
}

override fun onPause() {
    super.onPause()
    customWebView?.onPause()
}

override fun onDestroyView() {
    super.onDestroyView()
    customWebView?.stopLoading() // this should prevent onPageStarted() from being called
}

这个错误好像是你的Fragment是DestroyView时发生的。我对此不完全确定。您可以通过加载大型网页来重现,然后导航到另一个片段,以便执行 WebViewFragment / onViewDestroyed。在 onPageStarted 和 onPageFinished 中打印日志。如果您在销毁视图时看到它们被调用,这就是原因。此时您只需要检查生命周期状态以显示或隐藏进度。