您的位置:首页 > 移动开发

Webview内存泄漏与内存占用过大OOM的优化

2017-02-16 18:08 405 查看
1.首先不能直接在xml写webview组件,用FrameLayout做容器,java中动态添加:
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/video_desc_margin_top"></FrameLayout>
2.

FrameLayout ll = (FrameLayout) findViewById(R.id.content);
//        wvContent = new WebView(getApplicationContext());
wvContent = new WebView(weakReference.get());
ll.addView(wvContent);


3.销毁时要先销毁外部的容器:

@Override
protected void onDestroy() {
// Destroy the AdView.
if (wvContent != null) {
wvContent.removeAllViews();
ll.removeView(wvContent);
wvContent.destroy();
}
super.onDestroy();
}


4.再不行:

package com.mycompany.view;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.AttributeSet;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class NonLeakingWebView extends WebView {
private static Field sConfigCallback;

static {
try {
sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");
sConfigCallback.setAccessible(true);
} catch (Exception e) {
// ignored
}

}

public NonLeakingWebView(Context context) {
super(context.getApplicationContext());
setWebViewClient( new MyWebViewClient((Activity)context) );
}

public NonLeakingWebView(Context context, AttributeSet attrs) {
super(context.getApplicationContext(), attrs);
setWebViewClient(new MyWebViewClient((Activity)context));
}

public NonLeakingWebView(Context context, AttributeSet attrs, int defStyle) {
super(context.getApplicationContext(), attrs, defStyle);
setWebViewClient(new MyWebViewClient((Activity)context));
}

@Override
public void destroy() {
super.destroy();

try {
if( sConfigCallback!=null )
sConfigCallback.set(null, null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

protected static class MyWebViewClient extends WebViewClient {
protected WeakReference<Activity> activityRef;

public MyWebViewClient( Activity activity ) {
this.activityRef = new WeakReference<Activity>(activity);
}

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
try {
final Activity activity = activityRef.get();
if( activity!=null )
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}catch( RuntimeException ignored ) {
// ignore any url parsing exceptions
}
return true;
}
}
}


5.或者:通过反射清楚webview的内存占用

public void setConfigCallback(WindowManager windowManager) {
try {
Field field = WebView.class.getDeclaredField("mWebViewCore");
field = field.getType().getDeclaredField("mBrowserFrame");
field = field.getType().getDeclaredField("sConfigCallback");
field.setAccessible(true);
Object configCallback = field.get(null);

if (null == configCallback) {
return;
}

field = field.getType().getDeclaredField("mWindowManager");
field.setAccessible(true);
field.set(configCallback, windowManager);
} catch(Exception e) {
}
}


在Activity中回调:

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setConfigCallback((WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
}

public void onDestroy() {
setConfigCallback(null);
super.onDestroy();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: