Android 10:“由于在 UI 线程被阻止时在错误的线程上调用 WebView API,检测到可能出现死锁”

ily*_*ets 6 android android-webview android-softkeyboard

我的应用程序由带有全屏WebView 的Fragments组成。当用户单击WebView中的链接时,将打开新的Fragment ,其中包含具有相同URL的新WebView。打开新片段之前之前,我关闭软键盘以防万一。我打开新页面的速度非常快。所有操作都在主线程上执行。

根据 Crashlytics 的说法,该问题仅出现在 Android 10 上(所有 Pixel 系列设备和其他具有 10 的设备)。在 Android 10 之前的设备上一切正常。我可以打开很多碎片。但在 Android 10 设备上,这种情况会导致致命异常(随机快速尝试打开新页面 2-3 次后):

E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
Process: <myapp>, PID: 12487
java.lang.RuntimeException: Probable deadlock detected due to WebView API being called on incorrect thread while the UI thread is blocked.
    at Yp.a(PG:13)
    at com.android.webview.chromium.WebViewChromium.onCheckIsTextEditor(PG:4)
    at android.webkit.WebView.onCheckIsTextEditor(WebView.java:3035)
    at android.view.inputmethod.InputMethodManager.checkFocusNoStartInput(InputMethodManager.java:1901)
    at android.view.inputmethod.InputMethodManager.checkFocus(InputMethodManager.java:1863)
    at android.view.inputmethod.InputMethodManager.hideSoftInputFromWindow(InputMethodManager.java:1506)
    at android.view.inputmethod.InputMethodManager.hideSoftInputFromWindow(InputMethodManager.java:1475)
    at <myapp>.Utils.hideKeyboard(Utils.java:175)
    at <myapp>.openNewPage(Pager.java:210)
    ...
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:919)
 Caused by: java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask.get(FutureTask.java:206)
    at Yp.a(PG:11)
Run Code Online (Sandbox Code Playgroud)

我尝试使用Android System WebView的所有可用版本(稳定版、测试版、开发版、金丝雀版),但没有任何帮助。
有人可以帮助我吗?

更新
如果我评论隐藏软键盘的代码,那么一切正常。

小智 5

这不是解决方案,只是解释问题。

首先,你说“所有操作都在主线程上执行”,但这是错误的。堆栈树表明它位于工作线程中。

从源代码中也可以证实这一点。 WebView的阻塞任务

其次,Android Q 中的代码发生了变化,从该版本开始检查视图是文本编辑器

第三,您使用 View.post() 发布一项任务。它是在UI线程中,与WebView中的过程不同(即不需要等待和阻塞)

总之,InputMethodManager 在非 UI 线程中启动一个任务(WebView.onCheckIsTextEditor()),而 WebView 想要在 UI 线程中执行此任务,但由于超时(4 秒)没有得到结果。

所以是因为你在UI线程中做了太多的工作