天天看点

解决android中EditText导致的内存泄漏问题

开发中用到了LeankCanary,在一个简单的页面中(例如 :仅仅 包含Edittext),也会导致内训泄漏,为此,我在网上找了大量资料,最终解决。

例如一个布局:

<LinearLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

android:focusable="true"

android:focusableInTouchMode="true"

android:orientation="vertical">

<EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="12dp"
                android:background="@null"
                android:hint="4-20位不包含特殊字符"
                android:textSize="15dp" />           

<LinearLayout>

以上会导致内存泄漏,是由于EditText引用了Activity的context的原因,在Activity销毁的时候,

由于Edittext持有对Activity的context的引用,导致Activity无法正常回收。

解决办法:重写EditText,将对Activity中Context的引用,改为对ApplicationContext的引用。

代码如下:

@SuppressLint("AppCompatCustomView")

public class BaseEditText extends EditText {

private static java.lang.reflect.Field mParent;

static {
    try {
        mParent = View.class.getDeclaredField("mParent");
        mParent.setAccessible(true);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
}

public BaseEditText(Context context) {
    super(context.getApplicationContext());
}

public BaseEditText(Context context, AttributeSet attrs) {
    super(context.getApplicationContext(), attrs);
}

public BaseEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context.getApplicationContext(), attrs, defStyleAttr);
}

@SuppressLint("NewApi")
public BaseEditText(Context context, AttributeSet attrs, int defStyleAttr,
                    int defStyleRes) {
    super(context.getApplicationContext(), attrs, defStyleAttr, defStyleRes);
}

@Override
protected void onDetachedFromWindow() {
    try {
        if (mParent != null)
            mParent.set(this, null);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    }
    super.onDetachedFromWindow();
}           

}

然后xml中的布局引用自定义的EditText:

<包名.路径.BaseEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="12dp"
                android:background="@null"
                android:hint="4-20位不包含特殊字符"
                android:textSize="15dp" />