Solve the memory leak problem caused by EditText in android

LeankCanary is used in the development. In a simple page (for example, only including Edittext), it will also lead to internal training leakage. For this reason, I found a lot of information on the Internet and finally solved it.
For example, a layout:
<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 Bits do not contain special characters"
                android:textSize="15dp" />

<LinearLayout>

The above causes memory leakage. It is because EditText references the context of Activity. When the Activity is destroyed,
Activity cannot be recycled normally because Edittext holds a reference to the context of activity.
Solution: Rewrite EditText, change the reference to the Context in Activity to the reference to ApplicationContext.
The code is as follows:

@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();
}

}

Then the layout in xml refers to the customized EditText:

             <Package name.Route.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 Bits do not contain special characters"
                android:textSize="15dp" />

In addition, because LinearLayout gets the focus, it may also cause memory leakage,
You need to clear the focus in onDestroy in Activity:
LinearLayout.clearFocus();

Test again, problem solving!

Thank https://www.jianshu.com/p/e1b41fb80cdc The inspiration of the article.

Keywords: Android Java xml

Added by Pedro Sim on Wed, 11 Dec 2019 20:36:45 +0200