After a while of usage, my App freezes during scrolling a WebView, saying “could not lock surface”

后端 未结 3 1065
你的背包
你的背包 2020-12-15 23:49

My Android app consists of several activities, each responsible for a single fragment (for now). My fragments are usually displayed/attached somewhat like this:



        
相关标签:
3条回答
  • 2020-12-16 00:32

    I guess I fixed it. Apparently, there is a bug which prevents correct memory managment of the WebView. When I start many Activities with WebView in their views, the WebViews live in the memory and the activities are not properly killed when memory runs low. I worked around the issue with the following code in my TopicFragment which displays the WebView:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved) {
        View v = super.onCreateView(inflater, container, saved);
    
        mActivity = (BaseActivity) getSupportActivity();
    
        // this is the framelayout which will contain our WebView
        mWebContainer = (FrameLayout) v.findViewById(R.id.web_container);
    
        return v;
    }
    
    public void onResume() {
        super.onResume();
    
        // create new WebView and set all its options.
        mWebView = new WebView(mActivity);
        mWebView....
    
        // add it to the container
        mWebContainer.addView(mWebView);
    
        // if data is available, display it immediately
        if(mTopic != null) {
            mWebView.loadDataWithBaseURL("file:///android_asset/", mTopic.getHtmlCache(),
                    "text/html", "UTF-8", null);
        }
    }
    
    @Override
    public void onPause() {
        super.onPause();
    
        // destroy the webview
        mWebView.destroy();
        mWebView = null;
    
        // remove the view from the container.
        mWebContainer.removeAllViews();
    }
    

    This way, the WebView is created and removed in onResume and onPause. This is some overhead and not perfect, but it solves the memory issue and is barely noticable in terms of performance and so on.

    0 讨论(0)
  • 2020-12-16 00:44

    If you have many WebViews in your App in different Activities / Fragments than you could try to use a Pool where you can retrieve a WebView instance in the Activies onCreate() method and give the WebView back to the Pool in Activies onDestory().

    The WebViewPool size can be setup by users device memory class. This may not be the best solution for every app that uses webviews, but its a solution you can consider. You may need some testing etc.

    But keep in mind, Objects in a pool are not garbage collected, so be careful if you decide to use a Pool.

    0 讨论(0)
  • 2020-12-16 00:47

    I finally found the issue. Switching off hardware acceleration for the WebView solves it.

    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);
    }
    
    0 讨论(0)
提交回复
热议问题