MMike
MMike

Reputation: 598

MemoryLeak through onConfigurationChanged()

I have an AsyncTask which I need to "restart" if the user does configurations such as Switch Color.

When he do so I start the AsyncTask like this:

myWorkerClass.clearMemory();
    myWorkerClass = new WorkerClass(getApplicationContext(), gv, searchbar, width, scaleButtonText);
    myWorkerClass.execute();

In the AsyncTask I add a onTextChangeListener to my EditText!(Which causes the MemoryLeak later).

To prevent MemoryLeaks I have a Method in my AsyncTask which removes the onTextChangedListener:

public void clearMemory() {
    searchbar.removeTextChangedListener(myTextWatcher);
}

Everything works fine except when I rotate my device. When I rotate my Device I do only this in onConfigurationChanged:

myWorkerClass.clearMemory();
            myWorkerClass = new WorkerClass(getApplicationContext(), gv, searchbar, width, scaleButtonText);
            myWorkerClass.execute();

As you can see I do exactly the same thing as if the user changes a Color. But at rotating device I'm leaking Memory, at switching Color I'm not!

This is after switching the Color:

enter image description here

This is after rotating the Screen a few times (remember I do exactly the same as at switching color:

enter image description here

These are my Leak Suspects from the Heap Dump:

enter image description here

enter image description here

This is my dominator tree: enter image description here

Why do I know the onTextChangeListener is the Problem?

Because if I comment adding a onTextChangedListener to my EditText out, everything works fine. No Memory Leaks.

My Question:

Why does a Rotation Change leak Memory and a Color Change does not when I start the asynctask the exact same way and do exact the same things within the asynctask?

I searched a little bit: http://developer.android.com/guide/topics/resources/runtime-changes.html

But I can't figure out if that is my Problem. The Rotation must do something different, like creating a new activity because of that creating a new reference to my edittext. And because of that he can't remove the old onTextChangeListener.

Please understand. I don't want to make my whole code public. But I think this isn't necessary anyway in this case.

Upvotes: 0

Views: 383

Answers (2)

Lazy Ninja
Lazy Ninja

Reputation: 22537

In android, the rotation destroys your current activity to start a new one.
To avoid it, you can add android:configChanges="orientation|screenSize" in your manifest file.

Below are tips to avoid memory leaks on Rotation change

  1. Do not keep long-lived references to a context-activity (a reference to an activity should have the same life cycle as the activity itself)
  2. Try using the context-application instead of a context-activity
  3. Avoid non-static inner classes in an activity if you don't control their life cycle, use a static inner class and make a weak reference to the activity inside. The solution to this issue is to use a static inner class with a WeakReference to the outer class, as done in ViewRoot and its W inner class for instance
  4. A garbage collector is not an insurance against memory leaks

Source: Avoiding memory leaks

Upvotes: 0

marcinj
marcinj

Reputation: 50026

The Rotation must do something different, like creating a new activity because of that creating a new reference to my edittext.

exactly, it destroys your current activity and creates a new one. If searchbar is a member variable of your AsyncTask then consider putting it into WeakReference:

WeakReference<SearchBar> searchbarPtr; 

then access using searchBarPtr.get(), but check if its null, if so then it means it was garbage collected due to config change.

Also remember to not make your AsyncTask an inner class of you activity. If it is nested then make it static. Otherwise your asynctask will keep reference to your activity and it will prevent it from being destroyed - until its thread ends.

Unfortuanately making it all work corectly in all situations can be quite difficult and time consuming.

Hopefully no one will suggest preventing destruction of your activity through android:configChanges, implementing correct behaviour of your activity during rotation will prevent it from crashing/leaking in less common activity lifecycle moments which cannot be prevented by android:configChanges.

Upvotes: 0

Related Questions