首页 > 解决方案 > 带有接口引用的内存泄漏

问题描述

我有一个关于内存泄漏的问题。我有两个课程。

第一个是:

public class Utility {
private static Utility instance = null;
private UpdateListener listener;

//Make it a Singleton class
private Utility(){}
public static Utility getInstance() {
    if (instance == null)
        instance = new Utility();
    return instance;
}

public void setListener(UpdateListener listener) {
    this.listener = listener;
}

//Long running background thread
public void startNewTread() {
    new Thread (new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000 * 10);
                if (listener != null)
                    listener.onUpdate();
            } catch (InterruptedException e) {
                Log.d("Utility", e.getMessage());
            }
        }
    }).start();
}

//Listener interface
public interface UpdateListener {
    public void onUpdate();
}
}

第二类是:

public class ListenerLeak extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //Setting the listener
    Utility.getInstance().setListener(new Utility.UpdateListener() {
        @Override
        public void onUpdate() {
            Log.d("ListenerLeak", "Something is updated!");
        }
    });

    //Starting a background thread
    Utility.getInstance().startNewTread();
}

@Override
protected void onDestroy() {
    super.onDestroy();
}
}

在这个活动中。新的 Utility.UpdateListener 可能会造成内存泄漏吗?当活动被破坏时,只有Updatelistener可以活着。活动可以活着吗?

标签: androidmemory-leakslistener

解决方案


在 Utility 类中创建一个内部类,如下所示。然后将线程移动到该类。

 public void startNewTread() {
    new MyThread().start();
    }

 private static class MyThread extends Thread {
    @Override
    public void run() {
       try {
            Thread.sleep(1000 * 10);
            if (listener != null)
                listener.onUpdate();
        } catch (InterruptedException e) {
            Log.d("Utility", e.getMessage());
        }
    }
  }

原因:每次配置更改后,Android 系统都会创建一个新的 Activity,并将旧的 Activity 留在后面进行垃圾回收。但是,线程持有对旧 Activity 的隐式引用,并阻止它被回收。结果,每个新的 Activity 都会被泄露,并且与它们相关的所有资源都永远无法回收。https://www.androiddesignpatterns.com/2013/04/activitys-threads-memory-leaks.html将有助于理解它。


推荐阅读