I found the article "Avoiding memory leaks", where it is said that the following code:
private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
is not a good idea, since:
When the screen orientation changes the system will, by default, destroy the current activity and create a new one while preserving its state. In doing so, Android will reload the application's UI from the resources.
So the above code:
...leaks the first activity created upon the first screen orientation change. When a Drawable is attached to a view, the view is set as a callback on the drawable. In the code snippet above, this means the drawable has a reference to the TextView which itself has a reference to the activity (the Context) which in turns has references to pretty much anything (depending on your code.)
But, when screen orientation changes, the method setBackgroundDrawable(Drawable background) is called, which in turn calls:
background.setCallback(this);
The method Drawable.setCallback()
is definied in the following way:
public final void setCallback(Callback cb) {
mCallback = new WeakReference<Callback>(cb);
}
So, now background should release the old reference to the previous TextView, and a new reference to the new TextView should be created.
So, it seems like changing screen orientation leaks a reference only until the activity is newly created.
Where am I going wrong ?
The Memory Profiler is a component in the Android Profiler that helps you identify memory leaks and memory churn that can lead to stutter, freezes, and even app crashes. It shows a realtime graph of your app's memory use and lets you capture a heap dump, force garbage collections, and track memory allocations.
To find a memory leak, you've got to look at the system's RAM usage. This can be accomplished in Windows by using the Resource Monitor. In Windows 11/10/8.1: Press Windows+R to open the Run dialog; enter "resmon" and click OK.
DEFINITION A memory leak is the gradual deterioration of system performance that occurs over time as the result of the fragmentation of a computer's RAM due to poorly designed or programmed applications that fail to free up memory segments when they are no longer needed.
Memory leaks are a class of bugs where the application fails to release memory when no longer needed. Over time, memory leaks affect the performance of both the particular application as well as the operating system. A large leak might result in unacceptable response times due to excessive paging.
You are absolutely right. However, there is one subtle point: the article is from 2009. Back then, the implementation of setCallback
was different:
Android <= 2.3.7:
public final void setCallback(Callback cb) {
mCallback = cb;
}
Android >= 4.0.1:
public final void setCallback(Callback cb) {
mCallback = new WeakReference<Callback>(cb);
}
Grepcode shows no source code of intermediate versions, this is the only diff I could quickly find.
So, again, you're absolutely right in this specific case (if you're targeting >14 that is). However, it is still very important to really think about what is actually happening when you keep a static reference to such items (like you did). There are numerous cases where you certainly could be leaking the Context
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With