We have on a device a WebView which loads 10 pages with some javascript included. The problem is that is leaking and I don't know where could it be from. Basically there is an Activity which has ViewPager, and that ViewPager has .setAdapter on "new WebPagerAdapter()". WebPagerAdapter extends PagerAdapter.
The problem is that this is leaking somewhere and everything we tried is not working. It looks like on a device it jumps around 5-10mb constantly RAM usage but it is increasing just a little all the time, and after like a day it is on 150MB used. Heap dumps don't show anything useful and "dumpsys meminfo" shows more and more "Views" under Objects? I don't know what to try anymore, any suggestions?
This is instatiateItem on WebPagerAdapter
@Override
public Object instantiateItem(ViewGroup container, int position) {
NonLeakingWebView mwebView = new NonLeakingWebView(activity.getApplicationContext());
if (mWebViewClientLogScreen == null)
mWebViewClientLogScreen = new WebViewClientLogScreen(activity);
mwebView.setWebViewClient(mWebViewClientLogScreen);
mwebView.clearCache(true);
mwebView.setWebChromeClient(new WebChromeClient());
if (pos >= lenght)
pos = 0;
mwebView.getSettings().setJavaScriptEnabled(true);
mwebView.setTag(String.valueOf(pos));
mwebView.loadUrl(imageArray[pos]);
++pos;
// view.addView(mwebView);
container.addView(mwebView, 0);
return mwebView;
}
NonLeakingWebView is a WebView from https://stackoverflow.com/a/8949378/1088975
Destroy item
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
try {
NonLeakingWebView mWebView = (NonLeakingWebView) object;
container.removeView(mWebView);
mWebView.removeAllViews();
mWebView.clearHistory();
mWebView.clearView();
mWebView.clearCache(true);
mWebView.freeMemory();
mWebView.destroy();
Class.forName("android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(mWebView, (Object[]) null);
mWebView = null;
System.gc();
} catch (Exception e) {
e.printStackTrace();
}
container.removeView((View) object);
}
There is .onPause() because we tried to pause to see if there is any difference
public class NLAwebPager extends ViewPager {
public NLAwebPager(Context context) {
super(context);
}
public NLAwebPager(Context context, AttributeSet attr) {
super(context, attr);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
return true;
}
}
This is custom ViewPager which on main activity does this
NLPager= (NLAwebPager) findViewById(R.id.frame);
NLPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
WebView mWebVIew = (WebView) NLPager.findViewWithTag(--arg0);
if (mWebVIew != null)
mWebVIew.onPause();
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// Log.e("ss", "s");
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
And this is a Runnable which on every X seconds changes adapter page
private Runnable runnable_webPage = new Runnable() {
@Override
public void run() {
i = txtTime.getCurrentItem();
txtTime.setCurrentItem(++i, false);
mHandlerWebPage.removeCallbacks(runnable_webPage);
mHandlerWebPage.postDelayed(runnable_webPage, webPageChangeTimer);
}
};
And a custom WebViewClient for progress bar
public class WebViewClientLogScreen extends WebViewClient {
LogScreen wpa;
public WebViewClientLogScreen(FragmentActivity wpa) {
this.wpa = (LogScreen) wpa;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
try {
ProgressBar mbar = (ProgressBar) view.getTag();
mbar.setVisibility(View.GONE);
} catch (Exception e) {
}
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
try {
ProgressBar mbar = (ProgressBar) view.getTag();
mbar.setVisibility(View.VISIBLE);
} catch (Exception e) {
}
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
try {
wpa.doShowMessage();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
}