2

I am using WebViews in an Android app, and I need to prevent the WebViews from caching.

Unfortunately it seems like this seemingly simple goal is nearly impossible to achieve. The solution I have resorted to use is to execute webview.clearCache(true) in the onPageFinished event so that the cache is cleared each time a page is loaded. There are some issues...

I have noticed that as the cache grows it becomes very time consuming for the clearCache method to execute. Sometimes if you execute clearCache and then switch to a different Activity that contains different webview, that webview will not load for a few seconds because it is still waiting on the previous clearCache operation to finish.

What's worse is that execution time of subsequent calls to clearCache does not seem to decrease after the cache has been already cleared. If the call to clearCache takes 3 seconds to complete and then I immediately call clearCache a second time, then I would expect the second call to clearCache to complete almost immediately. But that is not what I'm experiencing; I'm experiencing that the second call to clearCache still take approximately 3 seconds.

Has anyone else experienced this? Is there any way to improve performance? Waiting 2-3 seconds for a webview to load (from the local filesystem) is horrible.

EDIT:

Here is my best alternative to actually clearing the cache. It more or less works but it's sort of flaky and I'm not 100% happy with it (written in Mono c#):

public class NoCacheWebClient : WebViewClient
{
    string previous;

    public override void OnPageStarted(WebView view, string url, Android.Graphics.Bitmap favicon)
    {
        base.OnPageStarted(view, url, favicon);

        if (!string.Equals(previous, url))
        {
            previous = url;
            view.Reload(); //re-load once to ignore cache
        }
        else
        {
            previous = null;
        }
    }
}
craigrs84
  • 3,048
  • 1
  • 27
  • 34

2 Answers2

7

1) Try using setAppCacheEnabled and setAppCacheMaxSize to limit the cache size to very little , lower cache size will result in faster cleanup.

Ex: wv.getSettings().setAppCacheMaxSize(1);

OR

2) If you don't need the cached data then simply set setCacheMode(WebSettings.LOAD_NO_CACHE); , which means "Don't use the cache, load from the network", even though data is cached.

In-short, simply ignore the cached data, android will take care of it.

OR

3) you can also try the below code for no-caching,

Note: this is only available for Android API 8+

    Map<String, String> noCacheHeaders = new HashMap<String, String>(2);
    noCacheHeaders.put("Pragma", "no-cache");
    noCacheHeaders.put("Cache-Control", "no-cache");
    view.loadUrl(url, noCacheHeaders);

OR

4) Clear the cache every-time whenever page load finishes. Something like this in the WebViewClient.

@Override
public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
    view.clearCache(true);
}

OR

5) You can try deleting whole cached database at once.

    context.deleteDatabase("webview.db");
    context.deleteDatabase("webviewCache.db");

This might give a bit faster result, hope so.

Moin Ahmed
  • 2,898
  • 21
  • 33
  • Thanks for the response. I've tried all these but none of them work well. Also I think setCacheMode, setAppCacheEnabled, and setAppCacheMaxSize are for HTML5 API caching, not caching in general. – craigrs84 Jan 18 '13 at 16:56
  • noCacheHeaders.put("Pragma", "no-cache"); is promising but I believe it only works on the base page that your are loading; if that page contains other resources such as images, then the no-cache will not be applied to those resources, only the base page. In this case the images will still be cached and will display the wrong content if the files have changed. I think I could fix that with WebViewClient.shouldInterceptRequest() but it is API Level 11+, and I need to target API Level 8+ – craigrs84 Jan 18 '13 at 17:05
  • have a look at onLoadResource(WebView view, String url) or shouldOverrideUrlLoading(WebView view, String url) as an alternative to the WebViewClient.shouldInterceptRequest(). – Moin Ahmed Jan 18 '13 at 17:39
  • Thanks. shouldOverrideUrlLoading is only called if the loading request is triggered by a user action, like click on a link. It will not work on other types of resources like just a plain image embedded in an HTML page. When onLoadResource is called, its too late to cancel or modify the request. – craigrs84 Jan 18 '13 at 19:03
1

As you are going to the next activity finish the previous activity. So that you can free all memory occupied by that activity. Hope this helps.

venkatvb
  • 681
  • 1
  • 9
  • 24
deepak825
  • 432
  • 2
  • 8
  • Thanks. I've tried finishing the activity but the time required to clear the cache was still the same (3-4 seconds). It seems that only once I force stopped the app that the time to clear the cache resets back to a reasonable time (a few milliseconds). – craigrs84 Jan 18 '13 at 17:01