美文网首页
关于Android EditText导致的内存泄漏的问题

关于Android EditText导致的内存泄漏的问题

作者: 程序员大耳 | 来源:发表于2021-09-27 11:29 被阅读0次

泄露信息如下:

====================================

    HEAP ANALYSIS RESULT

    ====================================

    1 APPLICATION LEAKS

    References underlined with "~~~" are likely causes.

    Learn more at https://squ.re/leaks.

    Displaying only 1 leak trace out of 4 with the same signature

    Signature: 645952c17f5aa992b39740a17b9afc2f3ccf5619

    ┬───

    │ GC Root: System class

    │

    ├─ android.os.AsyncTask class

    │    Leaking: NO (a class is never leaking)

    │    ↓ static AsyncTask.SERIAL_EXECUTOR

    │                      ~~~~~~~~~~~~~~~

    ├─ android.os.AsyncTask$SerialExecutor instance

    │    Leaking: UNKNOWN

    │    ↓ AsyncTask$SerialExecutor.mTasks

    │                              ~~~~~~

    ├─ java.util.ArrayDeque instance

    │    Leaking: UNKNOWN

    │    ↓ ArrayDeque.elements

    │                ~~~~~~~~

    ├─ java.lang.Object[] array

    │    Leaking: UNKNOWN

    │    ↓ Object[].[0]

    │              ~~~

    ├─ android.os.AsyncTask$SerialExecutor$1 instance

    │    Leaking: UNKNOWN

    │    Anonymous class implementing java.lang.Runnable

    │    ↓ AsyncTask$SerialExecutor$1.val$r

    │                                ~~~~~

    ├─ android.widget.TextView$3 instance

    │    Leaking: UNKNOWN

    │    Anonymous class implementing java.lang.Runnable

    │    ↓ TextView$3.this$0

    │                ~~~~~~

    ├─ androidx.appcompat.widget.AppCompatEditText instance

    │    Leaking: YES (View.mContext references a destroyed activity)

    │    View not part of a window view hierarchy

    │    View.mAttachInfo is null (view detached)

    │    View.mID = R.id.input_edit

    │    View.mWindowAttachCount = 1

    │    mContext instance of RoomMainActivity with mDestroyed = true

    │    ↓ View.mContext

    ╰→ RoomMainActivity instance

        Leaking: YES (ObjectWatcher was watching this because RoomMainActivity

        received Activity#onDestroy() callback and Activity#mDestroyed is true)

        key = cb388a5c-0ff2-452f-a9b0-6ea7d03a5105

        watchDurationMillis = 37631

        retainedDurationMillis = 32630

        mApplication instance of ChatApplication

        mBase instance of androidx.appcompat.view.ContextThemeWrapper

    ====================================

原因分析:

1、引用链结构:AsyncTask的SerialExecutor执行器引用了EditText对象,而EditText对象中的mContext引用到了RoomMainActivity中context,导致RoomMainActivity 无法销毁。

查看源码得知在TextView中有updateTextServicesLocaleAsync()方法,调用了AsyncTask.execute()向其中传入了匿名内部类Runnable,而持有了控件对象。

2、解决方法:因为在源码层面无法修改源码,在引用端切断引用链。

给EditText使用Application的上下文,在EditText使用的页面退出销毁时移除EditText控件,包括置空它的监听器、清除它的焦点。

import android.content.Context;

import android.os.Build;

import android.text.TextWatcher;

import android.util.AttributeSet;

import android.view.ViewGroup;

import androidx.appcompat.widget.AppCompatEditText;

/**

* 关于Android EditText导致的内存泄漏的问题

*/

public class NoMemoryLeakEditTextextends AppCompatEditText {

public NoMemoryLeakEditText(Context context) {

super(context.getApplicationContext());

    }

public NoMemoryLeakEditText(Context context, AttributeSet attrs) {

super(context.getApplicationContext(), attrs);

    }

public NoMemoryLeakEditText(Context context, AttributeSet attrs, int defStyleAttr) {

super(context.getApplicationContext(), attrs, defStyleAttr);

    }

public void clearMemoryLeak(TextWatcher watcher, ViewGroup container) {

clearFocus();

        setOnTouchListener(null);

        setOnClickListener(null);

        setOnDragListener(null);

        setOnKeyListener(null);

        setOnLongClickListener(null);

        setOnEditorActionListener(null);

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

setOnApplyWindowInsetsListener(null);

        }

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

setOnScrollChangeListener(null);

        }

setOnFocusChangeListener(null);

        removeTextChangedListener(watcher);

        container.removeView(this);

    }

}

最后在页面销毁的地方调用clearMemoryLeak方法

相关文章

网友评论

      本文标题:关于Android EditText导致的内存泄漏的问题

      本文链接:https://www.haomeiwen.com/subject/ysyhnltx.html