Android WebView Окно Утечка
Я столкнулся с этой проблемой в своем более крупном проекте, использующем WebView, но когда я не смог найти ничего неправильного в своем коде, я сделал простой проект, который содержит только две вещи:
MainActivity с этим конкретным кодом:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView) findViewById(R.id.webView);
Uri uri = Uri.parse("android.resource://whatever");
webView.loadUrl(uri.toString());
}
Activity_main.xml содержит только макет и веб-представление. Больше ничего.
Теперь webview отображает сообщение о том, что он не может отобразить веб-сайт, и это нормально. Не имеет значения, показывает он это или нет. И вот в чем дело: когда Я выбираю текст и всплывающее окно показывает (с копией / вставкой), а затем я возвращаюсь, нажав кнопку Назад (в результате чего закрывается действие), я получаю следующее исключение (без сбоя):
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7fb64bfadb20
E/WindowManager: android.view.WindowLeaked: Activity com.example.***.richwebeditor.MainActivity has leaked window android.widget.PopupWindow$PopupDecorView{ffd5bff V.E...... ........ 0,0-116,58} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:368)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:1258)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1032)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:995)
at org.chromium.content.browser.input.PopupTouchHandleDrawable.show(PopupTouchHandleDrawable.java:354)
at org.chromium.android_webview.AwContents.nativeOnDraw(Native Method)
at org.chromium.android_webview.AwContents.access$4500(AwContents.java:92)
at org.chromium.android_webview.AwContents$AwViewMethodsImpl.onDraw(AwContents.java:2731)
at org.chromium.android_webview.AwContents.onDraw(AwContents.java:1191)
at com.android.webview.chromium.WebViewChromium.onDraw(WebViewChromium.java:1713)
at android.webkit.WebView.onDraw(WebView.java:2486)
at android.view.View.draw(View.java:16178)
at android.view.View.updateDisplayListIfDirty(View.java:15174)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2615)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2434)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2067)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7fb63de30880
E/WindowManager: android.view.WindowLeaked: Activity com.example.***.richwebeditor.MainActivity has leaked window android.widget.PopupWindow$PopupDecorView{7220dcc V.E...... ........ 0,0-116,58} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:368)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:1258)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1032)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:995)
at org.chromium.content.browser.input.PopupTouchHandleDrawable.show(PopupTouchHandleDrawable.java:354)
at org.chromium.android_webview.AwContents.nativeOnDraw(Native Method)
at org.chromium.android_webview.AwContents.access$4500(AwContents.java:92)
at org.chromium.android_webview.AwContents$AwViewMethodsImpl.onDraw(AwContents.java:2731)
at org.chromium.android_webview.AwContents.onDraw(AwContents.java:1191)
at com.android.webview.chromium.WebViewChromium.onDraw(WebViewChromium.java:1713)
at android.webkit.WebView.onDraw(WebView.java:2486)
at android.view.View.draw(View.java:16178)
at android.view.View.updateDisplayListIfDirty(View.java:15174)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573)
at android.view.View.updateDisplayListIfDirty(View.java:15134)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2615)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2434)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2067)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7fb63de30340
Я протестировал его на трех разных устройствах Samsung Galaxy (Android 6.1), эмуляторе (7.0) и старом телефоне HTC (5.0). У меня есть исключения в каждом случае.
Сталкивался ли кто-нибудь с этой проблемой? Это ошибка с Android webview? Есть ли решение?
Править:
Экраны для справки о чем всплывающее окно, о котором я говорю:
3 ответов:
Похоже, что хорошим решением этой проблемы является вызов
webView.destroy()При завершении работы. Я считаю, что есть лучшее решение для этой проблемы и оставлю этот поток нерешенным на некоторое время, так что, возможно, кто-то, кто испытал его, поделится правильным способом его обработки.
Если вы хотите вернуться из своего веб-представления, используйте это в этом действии
@Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); // maybe you can even change this as needed } }
- вы создаете действие.
- порождает рабочий поток, который имеет ссылки на это действие. - Действие закрывается / завершается()каким-то образом (скорее всего, в результате взаимодействия с пользователем), и система пытается собрать свои ресурсы.
- каким-то образом этот рабочий поток все еще работает и содержит ссылки на действие... таким образом, активность "утекла", и система не может свободно восстанавливайте его, не изменяя/не искажая состояние приложения потенциально опасными способами.
-действия являются тяжеловесными объектами в Android, и (агрессивный) системный менеджер ресурсов должен иметь возможность вернуть их, чтобы обеспечить плавный и эффективный опыт для пользователя. Так что эта "утечка" считается ошибкой.
- в этих случаях проверка ссылок все еще существует до ваших действий
Возможно, вам следует освободить ресурс, используемый
WebView, прежде чем завершить Действие, попробуйте добавитьwebView.loadUrl("about:blank");вonDestroy()
Comments