带有接口引用的内存泄漏 [英] Memory leak with interface referance

查看:337
本文介绍了带有接口引用的内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于内存泄漏的问题.我有两个类.

I have a question about memory leak.I have two classes.

第一个是:

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可以存活.活动可以存活吗?

in this activity.May new Utility.UpdateListener create a memory leak? when the activity destoroyed , only Updatelistener can be alive.does activity can be alive?

推荐答案

泄漏仅表示不再使用类的对象,但系统无法回收它们所驻留的内存(堆内存).发生这种情况是因为至少有一个强引用保持引用该对象.

Leak simply means when an object of a class is no longer used but the system cannot reclaim memory where they live on (heap memory). This happens because there is at least one strong reference keep refer to the object.

回到您的情况.

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

您创建实现Utility.UpdateListener接口的匿名内部类(没有名称的类),并使用new关键字创建匿名内部类的匿名对象,但不保留对该对象的任何引用.

You create an anonymous inner class (class which no name) which implements Utility.UpdateListener interface and you create an anonymous object of the anonymous inner class as well by using new keyword but do not keep any reference to the object.

在Java中,当您声明一个内部类时,它将保留对外部类的引用(在本例中为ListenerLeak活动).

In Java when you declare an inner class, it will keep a reference to outer class (in this case ListenerLeak activity).

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

startNewTread方法中,您创建并启动一个后台线程.

In startNewTread method, you create and start a background thread.

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

再次在此类中创建一个实现Runnable接口的匿名类,并创建一个Thread类的匿名对象.结果,线程保留对Utility类的引用.这是参考链

Again in this class you create an anonymous class which implements Runnable interface and you create an anonymous object of Thread class. As a result, the thread keep a reference to Utility class. This is reference chain

Background Thread -> Utility -> Listener -> ListenerLeak (the activity)

当用户在活动上按返回键时.此时,活动将被更长时间使用,并且系统可以回收活动所在的内存.不幸的是,由于后台线程仍然保留对它的引用,因此系统为何无法回收内存.结果,发生泄漏.

When users press back key on the activity. At this time the activity is longer used and the system can reclaim memory where the activity live on. Unfortunately, because the background thread is still keep a reference to it so that why the system cannot reclaim the memory. As a result, a leak occurs.

解决方案::当用户按返回键时,在销毁活动之前,系统将调用"onDestroy"方法.在这种方法中,您应该从后台线程中删除对该活动的引用.

Solution: When users press back key, before destroy the activity, the system will call 'onDestroy' method. In this method you should remove the reference from the background thread to this activity.

@Override
protected void onDestroy() {
    Utility.getInstance().setListener(null);
    super.onDestroy();
}

这是参考链

Background Thread -> Utility -> Listener -> null (point to nothing)

并且现在没有针对该活动的强引用,因此系统将回收内存并且不会发生泄漏.

And now there is no strong reference refer to the activity, so the system will reclaim the memory and no leak occur.

这篇关于带有接口引用的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆