【问题标题】:Android Handler, memory leak?Android Handler,内存泄漏?
【发布时间】:2023-08-17 15:40:01
【问题描述】:

我了解 Handler 可能会在 Android 中泄漏内存,但我不太确定我所做的是否正确:

public class MyActivity extends Activity
{

Handler handler;
HashMap<String, String> bigData = new HashMap<String, String>();

protected void onCreate(undle savedInstanceState) {
    super.onCreate(savedInstanceState);
    handler = new WeakHandler(){
        public void handlerMessage(Message msg, Context conetxt)
        {
           // i think this usage is wrong, still leak, am I right?
           Log.v("MyActivity", bigData.get("abc"))
        }
    }
};


static class WeakHandler extends Handler {

    private final WeakReference<Context> ref;

    public WeakHandler(Context t) {
        super();
        ref = new WeakReference<Context>(t);
    }

    @Override
    public final void handleMessage(Message msg) {
        final Context context = ref.get();
        if (context != null) {
            handleMessage(msg, context);
        }
    }

    public void handlerMessage(Message msg, Context conetxt)
    {

    }

 }

另外,如果我只想使用 Handler 来“发布”、“postDelayed”、“removeCallbacks”,我不关心 handleMessage,那么创建一个新的 Handler 实例来执行这些操作是否安全,如下所示:

new Handler().postDelayed(some Runnable);

【问题讨论】:

  • 请参考 here 获取 android 中的处理程序帮助

标签: android multithreading memory handler memory-leaks


【解决方案1】:

使用 MAT Analyzer 检查内存泄漏。 http://www.youtube.com/watch?v=_CruQY55HOk。 谈话是关于内存泄漏的。

我猜对上下文的引用会导致泄漏。使用 getApplicationContext();

只要您的应用程序存在,此上下文就会存在。

http://android-developers.blogspot.in/2009/01/avoiding-memory-leaks.html.

【讨论】:

    【解决方案2】:

    当你实例化 WeakHandler 时,它不会是一个实际的 WeakHandler 类,而是一个扩展 WeakHandler 类的匿名类。 Anonymous 类永远不会是静态的,因此除了显式 WeakReference 之外,它还会隐式引用包含的类(即 MyActivity)。

    由于 onCreate() 在主线程上运行,在 onCreate() 内部创建的 Handler 将与主线程(实际上是应用程序启动时创建的主 Looper)相关联。如果您向 Handler 发布 Message(或 Runnable,因为 Runnable 将被 Message 包裹),则该 Message/Runnable 将具有对 Handler 的引用。

    因此,鉴于您 postDelayed 延迟了 5 分钟。销毁 Activity 后(例如,因为旋转),主 Looper 将引用 Message/Runnable,Message/Runnable 将引用 Handler,Handler 将引用 Activity 5 分钟。这是一个泄漏。

    是的,"Log.v("MyActivity", bigData.get("abc"))" 行也泄露了活动。

    【讨论】:

    • 我相信你的解释是不正确的。实际上,原始问题中所做的事情是正确的。因为 WeakHandler 是一个静态内部类,所以它没有使用对父类的隐式引用来实例化。使用静态类和弱引用的原始问题方法实际上是解决泄漏处理程序androiddesignpatterns.com/2013/01/…的推荐方法。
    • WeakHandler 是静态的,但在 onCreate 中 WeakHandler 类被扩展,并且声明和实例化了一个新的(非静态的)匿名类。所以这个匿名类确实有对上下文的引用。如果该行是handler = new WeakHandler(this);(注意,没有额外的括号来声明一个新类),那么你是对的。
    • 是的,没错,我似乎忽略了匿名类的创建。谢谢指正!