1. 程式人生 > >解決android中EditText導致的內存泄漏問題

解決android中EditText導致的內存泄漏問題

大量 can eset efs extends attribute 自定義 lec hint

開發中用到了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" />

另外,由於LinearLayout獲取了焦點,也可能會導致內存的泄漏,
需要在Activity中的onDestroy裏清除掉焦點:
LinearLayout.clearFocus();

再次測試,問題解決!

感謝 https://www.jianshu.com/p/e1b41fb80cdc 文章的啟發。

解決android中EditText導致的內存泄漏問題