在调试一个android APP时,重复的调用创建一个webview Activity,盯着android studio 的 Android Profiler看,发现Memery占用从300M慢慢的叠加到了1个G,最后发生GC强制回收内存,屏幕闪烁一下后,App自动重启回到主页界面。
一开始以为是WebView未释放内存的原因,就去找了释放WebView内存的方法。有说法webview在布局文件内配置,内存是无法主动释放的。webView的推荐配置是动态生成,Activity销毁时主动释放内存。
private RelativeLayout mywebLayout;
private WebView web;
@Override
protected void onCreate(Bundle savedInstanceState) {
mywebLayout = (RelativeLayout) findViewById(R.id.mywebLayout);
web = new WebView(this);
web.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
mywebLayout.addView(web);
}
@Override
public void onDestroy() {
super.onDestroy();
mywebLayout.removeView(web);
web.removeAllViews();
web.destroy();
}
然后我发现自己后来又踩了个坑:
WebView Activity 在注册表里配置为singTask单例模式, 在WebView Activity内声明变量private WebView web,在动态生成webview时又声明了一次
WebView web = new WebView(this);
导致每次生成一个新的WebView对象,原有的WebView对象永远无法释放,导致内存爆炸
优化结果:
private RelativeLayout mywebLayout;
private WebView web = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
overridePendingTransition(0, 0);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_load_web);
initView();
initListener();
initData();
}
private void initView() {
mywebLayout = (RelativeLayout) findViewById(R.id.mywebLayout);
}
@Override
public void onDestroy() {
super.onDestroy();
mywebLayout.removeView(web);
web.removeAllViews();
web.destroy();
}
private void initData() {
setWebView();
}
private void setWebView() {
if(web == null) {
web = new WebView(this);
web.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
mywebLayout.addView(web);
}
String url = getIntent().getStringExtra("url");
web.getSettings().setJavaScriptEnabled(true); //加上这一行网页为响应式的
web.getSettings().setPluginState(WebSettings.PluginState.ON);
web.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
web.getSettings().setAllowFileAccess(true);
web.getSettings().setDefaultTextEncodingName("UTF-8");
web.getSettings().setLoadWithOverviewMode(true);
web.getSettings().setUseWideViewPort(true);
web.setInitialScale(100);
web.loadUrl(url);
web.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true; //返回true, 立即跳转,返回false,打开网页有延时
}
/**
* 处理ssl请求
*/
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
@Override
public void onPageFinished( WebView view, String url) {
web.clearCache(true);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
});
web.setWebChromeClient(new WebChromeClient() {
/**
* 显示自定义视图,无此方法视频不能播放
*/
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
}
});
}