【问题标题】:Kotlin 1.5.0 NPE when properly destroying a WebView正确销毁 WebView 时的 Kotlin 1.5.0 NPE
【发布时间】:2021-09-17 14:01:22
【问题描述】:

我的应用程序按照以下方式销毁 webviews(来自here)。

 parentConstraintLayout.removeView(webView)
 webView.apply{
     clearHistory()
     clearCache(true)
     loadUrl("about:blank")
     onPause()
     removeAllViews()
 }

在将 Kotlin 版本从 1.4.32 升级到 1.5.0 之前一直运行良好 在 Kotlin 1.5.0 中,执行 parentConstraintLayout.removeView(webView) 后 webView 变量变为 null。 clearHistory() 抛出 NPE 并且应用程序崩溃。 webViewparentConstraintLayout 都在 XML 中声明。

我已验证其他一切都相同,Kotlin 1.5.0 / 1.5.20 会出现此问题,但 1.4.32 不会出现此问题。为什么升级 Kotlin 会出现这种情况,我可以做些什么来解决它?

这里是webView

<WebView
     android:id="@+id/webView"
     android:layout_width="0dp"
     android:layout_height="0dp"
     app:layout_constraintTop_toBottomOf="@id/webViewToolbarContainer"
     app:layout_constraintLeft_toLeftOf="parent"
     app:layout_constraintRight_toRightOf="parent"
     app:layout_constraintBottom_toBottomOf="parent"
/>

parentConstraintLayout - 它是直接父母

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/parentConstraintLayout"
>

这是崩溃日志

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.webkit.WebView.clearHistory()' on a null object reference
       at com.myapp.android.screens.sweepstakes.ui.DetailActivity.destroyWebView(DetailActivity.java:25)
       at com.myapp.android.screens.ui.DetailActivity.close(DetailActivity.java:21)
       at com.myapp.android.screens.impl.DetailParentPresenter.onTerminationDialogOptionSubmitClicked(DetailParentPresenter.java:69)
       at com.myapp.android.screens.ui.DetailActivity$showSubsequentTerminationDialog$1.invoke(DetailActivity.java:26)
       at com.myapp.android.screens.ui.DetailActivity$showSubsequentTerminationDialog$1.invoke(DetailActivity.java:2)
       at com.afollestad.materialdialogs.callbacks.DialogCallbackExtKt.invokeAll(DialogCallbackExtKt.java:26)
       at com.afollestad.materialdialogs.MaterialDialog.onActionButtonClicked$core(MaterialDialog.java:34)
       at com.afollestad.materialdialogs.internal.button.DialogActionButtonLayout$onFinishInflate$1.onClick(DialogActionButtonLayout.java:8)
       at android.view.View.performClick(View.java:7448)
       at android.view.View.performClickInternal(View.java:7425)
       at android.view.View.access$3600(View.java:810)
       at android.view.View$PerformClick.run(View.java:28305)
       at android.os.Handler.handleCallback(Handler.java:938)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:223)
       at android.app.ActivityThread.main(ActivityThread.java:7664)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

【问题讨论】:

  • 请提供您的崩溃日志以获取更多详细信息
  • 最后添加
  • @user1114 你找到原因了吗?我面临着一个类似的问题,removeView 调用使 Kotlin Synthetics 变量变为空。在 Kotlin 1.5 之前没有发生这种情况,但我无法在更改日志中找到任何相关原因。

标签: android kotlin webview kotlin-android-extensions kotlin-1.5


【解决方案1】:

您可以覆盖 loadWebView。在加载 Web 视图之前,您可以清除数据和 cookie

    override fun loadWebView(userAccessToken: Token) {
    mWebView.clearCache(true)
    mWebView.clearFormData()
    mWebView.clearHistory()
    CookieManager.getInstance().removeAllCookies(null)
    CookieManager.getInstance().flush()
    mWebView.webViewClient = object : BaseWebViewClient() {
        override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
           // TODO url validator return true/false

        }
    }
    mWebView.loadUrl(uri.toString())
}

【讨论】:

    【解决方案2】:

    1.5.0 上的 Kotlin 合成器在您每次引用它时都会调用 findViewById(),而不是在 1.4.x 上使用缓存的。由于您已将其从视图中删除,因此 findViewById() 返回 null。

    你可以改用这个:

     webView.apply{
         parentConstraintLayout.removeView(this)
         clearHistory()
         clearCache(true)
         loadUrl("about:blank")
         onPause()
         removeAllViews()
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 2015-01-10
      相关资源
      最近更新 更多