android webview内存泄漏,Android由webview引起的内存泄漏

业务场景:MainActivity中有4个tab,分别为 webview加载斗鱼主页,视频播放,webview加载五星体育,地图等四个模块。在加载web的时候发现内存泄露。

首先不能直接在xml写webview组件,用FrameLayout做容器,java中动态添加:

...

mWebView = new WebView(MyApplication.getContext());

mLlayout_webview.addView(mWebView);

弱引用

经测试,通过给webview所在的activity设置为独立进程,然后在改activity的ondestory()方法干掉进程就可以了。Acitvity中的代码

@Override

protected void onDestroy() {

unbinder.unbind();

if (EventBus.getDefault().isRegistered(this)) {

EventBus.getDefault().unregister(this);

}

tellServiceUnbind();

unbindService(serviceConnection);

releaseResource();

/**

* 解决Activity中

* https://www.cnblogs.com/ganchuanpu/p/9182968.html

* 为加载WebView的界面开启新进程,在该页面退出之后关闭这个进程。

*/

android.os.Process.killProcess(android.os.Process.myPid());

super.onDestroy();

}

完整的webview 代码

public class WuXingFragment extends BaseFragment {

private WebSettings webSettings;

public static WuXingFragment getInstance() {

WuXingFragment fragment = new WuXingFragment();

return fragment;

}

private static final String url = "http://sports.sina.com.cn/gsports.shtml#263363145";

private View mView;

private WebView mWebView;

private RelativeLayout loading_over;

private boolean isSuccess = false;

private boolean isError = false;

private LinearLayout ll_control_error,mLlayout_webview;

@Nullable

@Override

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

mView = inflater.inflate(R.layout.layout_webview, container, false);

mWebView = new WebView(MyApplication.getContext());

mLlayout_webview = mView.findViewById(R.id.llayout_webview);

mLlayout_webview.addView(mWebView);

return mView;

}

@Override

public void onResume() {

super.onResume();

// webview 优化 据说可以省电

webSettings.setJavaScriptEnabled(true);

}

@Override

public void onStop() {

super.onStop();

// webview 优化 据说可以省电

webSettings.setJavaScriptEnabled(false);

}

private void doAction() {

webSettings = mWebView.getSettings();

mWebView.setInitialScale(25);

webSettings.setJavaScriptEnabled(true);

webSettings.setJavaScriptEnabled(true);

webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

webSettings.setUseWideViewPort(true);//关键点

webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);

webSettings.setDisplayZoomControls(false);

webSettings.setJavaScriptEnabled(true); // 设置支持javascript脚本

webSettings.setAllowFileAccess(true); // 允许访问文件

// webSettings.setBuiltInZoomControls(true); // 设置显示缩放按钮

// webSettings.setSupportZoom(true); // 支持缩放

webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);

webSettings.setDomStorageEnabled(true);

webSettings.setPluginState(WebSettings.PluginState.ON);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

}

mWebView.loadUrl(url);

//设置视图客户端

mWebView.setWebViewClient(new MyWebViewClient(getActivity()));

// mWebView.setWebViewClient();

}

class MyWebViewClient extends WebViewClient {

protected WeakReference activityRef;

public MyWebViewClient(Activity activity) {

this.activityRef = new WeakReference<>(activity);

}

@Override

public boolean shouldOverrideUrlLoading(WebView view, String url) { //重写此方法表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边

if (this == null) {

return false;

}

Activity activity = activityRef.get();

if (activity != null) {

//调用拨号程序

if (url.startsWith("mailto:") || url.startsWith("geo:") || url.startsWith("tel:") || url.startsWith("smsto:")) {

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));

activity.startActivity(intent);

return true;

}

}

return false;

}

@Override

public void onPageFinished(WebView view, String url) {

}

@Override

public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {

//6.0以下执行

updateUI();

}

@Override

public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {

super.onReceivedError(view, request, error);

//6.0以上执行

updateUI();

}

}

private void updateUI() {

isError = true;

isSuccess = false;

mWebView.setVisibility(View.GONE);

ll_control_error.setVisibility(View.VISIBLE);

}

@Override

public void onDestroyView() {

release();

super.onDestroyView();

}

@Override

public void onDestroy() {

release();

super.onDestroy();

}

private void release() {

if (null != mWebView) {

// 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再

// destory()

ViewParent parent = mWebView.getParent();

if (parent != null) {

((ViewGroup) parent).removeView(mWebView);

}

mWebView.stopLoading();

// 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错

mWebView.getSettings().setJavaScriptEnabled(false);

mWebView.clearHistory();

mWebView.clearView();

mWebView.removeAllViews();

mWebView.destroy();

}

releaseAllWebViewCallback();

}

// 这个方法我这里暂时没起作用

public void releaseAllWebViewCallback() {

if (android.os.Build.VERSION.SDK_INT < 16) {

try {

Field field = WebView.class.getDeclaredField("mWebViewCore");

field = field.getType().getDeclaredField("mBrowserFrame");

field = field.getType().getDeclaredField("sConfigCallback");

field.setAccessible(true);

field.set(null, null);

} catch (NoSuchFieldException e) {

if (BuildConfig.DEBUG) {

e.printStackTrace();

}

} catch (IllegalAccessException e) {

if (BuildConfig.DEBUG) {

e.printStackTrace();

}

}

} else {

try {

Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");

if (sConfigCallback != null) {

sConfigCallback.setAccessible(true);

sConfigCallback.set(null, null);

}

} catch (NoSuchFieldException e) {

if (BuildConfig.DEBUG) {

e.printStackTrace();

}

} catch (ClassNotFoundException e) {

if (BuildConfig.DEBUG) {

e.printStackTrace();

}

} catch (IllegalAccessException e) {

if (BuildConfig.DEBUG) {

e.printStackTrace();

}

}

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值