使用一段时间后,我的应用程序在滚动WebView时冻结,说"无法锁定表面"

jan*_*ver 11 android webview android-webview

我的Android应用程序由几个活动组成,每个活动负责一个片段(现在).我的片段通常显示/附加有点像这样:

mTopicFragment = (TopicFragment)getSupportFragmentManager().findFragmentByTag("topic");
if(mTopicFragment == null)
    mTopicFragment = TopicFragment.newInstance(bid, page, pid);

if (savedInstanceState == null) {
    getSupportFragmentManager().beginTransaction()
            .add(R.id.content, mTopicFragment, "topic")
            .commit();
}
Run Code Online (Sandbox Code Playgroud)

TopicFragment包含一个WebView显示某些HTML和CSS/JS的东西.浏览应用程序一段时间后,其中一个TopicFragmentWebView中的滚动变得缓慢,最终,应用程序完全冻结.ADB日志显示以下异常:

12-12 22:49:33.931  12582-12582/com.mde.potdroid3 W/Adreno-EGLSUB? <DequeueBuffer:606>: dequeue native buffer fail: Unknown error 2147483646, buffer=0x0, handle=0x0
12-12 22:49:33.941  12582-12582/com.mde.potdroid3 W/Adreno-EGLSUB? <DequeueBuffer:606>: dequeue native buffer fail: Invalid argument, buffer=0x0, handle=0x0
12-12 22:49:33.941  12582-12582/com.mde.potdroid3 W/Adreno-ES20? <gl2_surface_swap:43>: GL_OUT_OF_MEMORY
12-12 22:49:33.941  12582-12582/com.mde.potdroid3 W/Adreno-EGL? <qeglDrvAPI_eglSwapBuffers:3597>: EGL_BAD_SURFACE
12-12 22:49:33.941  12582-12582/com.mde.potdroid3 W/HardwareRenderer? EGL error: EGL_BAD_SURFACE
12-12 22:49:33.951  12582-12582/com.mde.potdroid3 W/HardwareRenderer? Mountain View, we've had a problem here. Switching back to software rendering.

12-12 22:20:04.461  10081-10081/com.mde.potdroid3 E/Surface? dequeueBuffer failed (Unknown error 2147483646)
12-12 22:20:04.461  10081-10081/com.mde.potdroid3 E/ViewRootImpl? Could not lock surface
    java.lang.IllegalArgumentException
            at android.view.Surface.nativeLockCanvas(Native Method)
            at android.view.Surface.lockCanvas(Surface.java:243)
            at android.view.ViewRootImpl.drawSoftware(ViewRootImpl.java:2435)
            at android.view.ViewRootImpl.draw(ViewRootImpl.java:2409)
            at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2253)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1883)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
            at android.view.Choreographer.doCallbacks(Choreographer.java:574)
            at android.view.Choreographer.doFrame(Choreographer.java:544)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5081)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:781)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
Run Code Online (Sandbox Code Playgroud)

在互联网上,我只能找到有关此例外的信息,其中人们拥有自定义视图.这里发生了什么?它可以与我的应用程序的内存消耗有关吗?看起来好像每次调用上面的代码时,TopicFragment都会实例化,显示并推送到后台.我怎么能进一步调试这种行为?


还有一个信息:当我在开发人员设置中启用叠加时,应用程序似乎使用了很多CPU.可能是这样,当我离开它们并且出于某种原因继续在后台运行时,我的碎片没有被正确分离?


这就是我使用WebView的方式:

mWebView = (WebView)getView().findViewById(R.id.topic_webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
mWebView.getSettings().setAllowFileAccess(true);
mWebView.addJavascriptInterface(mJsInterface, "api");
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.loadData("", "text/html", "utf-8");
mWebView.setBackgroundColor(0x00000000);
Run Code Online (Sandbox Code Playgroud)

不是这里提到的内存泄漏.

jan*_*ver 0

我终于找到问题了。关闭 WebView 的硬件加速即可解决此问题。

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved) {
    //...
    if (Utils.isKitkat()) {
        disableHardwareAcc();
    }
    //...
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
protected void disableHardwareAcc() {
    mWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
Run Code Online (Sandbox Code Playgroud)