10

I am displaying a fairly large image in a webview so that the pinch-to-zoom functions and other conveniences for viewing are already available.

It displays correctly the first time. But after leaving the activity and coming back to it, the app crashes on an OutofMemoryError related to the webview thread.

I have attempted several things to try to close the webview or stop the thread, or clear its use of memory, but to no avail. Here are examples of code that I added to my activities' onStop() function

    wv.stopLoading();
    wv.clearCache(true);
    //removeView(wv);
    wv.clearView();
    wv.freeMemory();
    wv.destroy();
    try {
        Class.forName("android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(wv, (Object[]) null);
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Anyway feel free to criticize any of those lines of code, but the point is that they have no influence on the error at all! It has to do with the webviewcore thread itself not releasing memory.

This is alarming to me because even if I was using a smaller image, this looks like it would still eventually happen. Help?

CQM
  • 42,592
  • 75
  • 224
  • 366
  • when you leave the activity call `webView.destroy()`. You can do it by destroying the webview in the `onDestroy()` of your activity – Varun Jun 20 '11 at 17:43
  • Didn't work. `protected void onDestroy(){ super.onDestroy(); wv.destroy(); }` Still got OutofMemoryError when I loaded the activity a second time. – CQM Jun 20 '11 at 17:56
  • hmmm.. try removing the code from your `onStop()` method. and try to destroy your `webview` before you call `super.onDestroy()` – Varun Jun 20 '11 at 18:01
  • This has no influence either :( – CQM Jun 20 '11 at 18:14
  • +1 This clean up code was very helpful – Mark Lapasa Sep 18 '12 at 22:12

3 Answers3

3

Okay, so the conclusion to this issue was that the String buffer could not be predetermined or properly cleared at these file sizes.

In this case the image was pulled from a server as a string, manipulated as a string and finally displayed as an image.

Whether displayed as an ImageView or as a Webview, it did not matter, the app would crash once a string buffer became full (which it would not clear no matter how much stuff I freed or set to null), This was an encryption effort.

but Finally just settled with storing the images in the app's assets folder.

CQM
  • 42,592
  • 75
  • 224
  • 366
  • @Pablo I use URLImageViewHelper on github, I've also contributed to that project – CQM Jan 21 '13 at 15:29
2

Efficient way ever:

WebViewActivity.java

public class WebViewActivity extends AppCompatActivity {

    private WebView mWebView;
    private RelativeLayout mWebViewParent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_view);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mWebViewParent = (RelativeLayout) findViewById(R.id.layoutWebViewParent);
        mWebView = (WebView)findViewById(R.id.webView);

        // Other stuff

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        destroyWebView();
    }

    private void destroyWebView() {
        mWebViewParent.removeAllViews();
        if(mWebView != null) {
            mWebView.clearHistory();
            mWebView.clearCache(true);
            mWebView.loadUrl("about:blank");
            mWebView.freeMemory();
            mWebView.pauseTimers();
            mWebView = null;
        }
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}

activity_web_view.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/layoutWebViewParent" >

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </WebView>

</RelativeLayout>

AndroidManifest.xml

<activity
    android:name=".WebViewActivity"
    android:label="@string/title_activity_web_view"
    android:process="webview.kill">
</activity>

Hope this will help you.

Hiren Patel
  • 52,124
  • 21
  • 173
  • 151
2

Maybe try recycling the bitmap/image?

If that doesn't work, I suggest re-sampling it.

Strange out of memory issue while loading an image to a Bitmap object

Community
  • 1
  • 1
hwrdprkns
  • 7,525
  • 12
  • 48
  • 69
  • I am pulling my image down as an encrypted string. No bitmap functions are called. The webview is using the loadData function with the proper mimetype. – CQM Jun 20 '11 at 20:06
  • ReadWriteCharArrayBuffer isn't allocating enough memory on the second go around. (the image comes in as string) How do I allocate say... 1024000 of memory – CQM Jun 20 '11 at 20:20
  • 1
    You cannot allocate memory on the Android device. I remember some GoogleIO session where Romain Guy was just like "you never know how much memory your app is going to get so use as little as possible all the time". That said, it might be a long string with a huge decryption process? Try to `finalize()` some stuff in there maybe? Or call a System.gc() right before you load your webview? – hwrdprkns Jun 20 '11 at 20:36