I have a question about memory leak.I have two classes.
The first one is:
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();
}
}
Thesecond class is:
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();
}
}
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.
Back to your case.
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 usingnew
keyword but do not keep any reference to the object.In Java when you declare an inner class, it will keep a reference to outer class (in this case
ListenerLeak
activity).In
startNewTread
method, you create and start a background thread.Again in this class you create an anonymous class which implements
Runnable
interface and you create an anonymous object ofThread
class. As a result, the thread keep a reference toUtility
class. This is reference chainWhen 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.
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.
Here is the reference chain
And now there is no strong reference refer to the activity, so the system will reclaim the memory and no leak occur.
Create an inner class inside a Utility class like below. Then move the thread to that class.
Reason: After each configuration change, the Android system creates a new Activity and leaves the old one behind to be garbage collected. However, the thread holds an implicit reference to the old Activity and prevents it from ever being reclaimed. As a result, each new Activity is leaked and all resources associated with them are never able to be reclaimed. https://www.androiddesignpatterns.com/2013/04/activitys-threads-memory-leaks.html will help to understand it.