Skip to content Skip to sidebar Skip to footer

Weak Reference Instead Of Getactivity() (android Avoid Memory Leak)?

To avoid a memory leak I wrote the following method that will be used in activities and mainly in fragments (using inheritance). That method is supposed to allow me to never direct

Solution 1:

It is totally feasible. For example you have this pseudocode code:

publicclassMainActivityextendsActivity {

    @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

         newDownloadTask().execute();
    }

    publicvoidshowInfo() {
    }

    classDownloadTaskextendsAsyncTask<Void, Void, Void> {
        @OverrideprotectedVoiddoInBackground(Void... params) {
            returnnull;
        }

        @OverrideprotectedvoidonPostExecute(Void data) {
            // we can call showInfo() activity because Asynctask hold an implicit reference to activity showInfo();
        }
    }
}

On above code, there is a situation will caused memory leak.

Here is the explanation:

When you create DownloadTask as above example, java call DownloadTask is an inner class. An inner class will implicit holds a reference to outer class, in this case is MainActivity. Moreover, when you start an asynctask, that asynctask will be held by system until it finish. For example, you download takes 30 seconds. In that 30 seconds, you rotate your device. When you rotate your device, MainActivity is re-created and often old activity will be destroyed. But in this case old activity isn't destroyed because the old MainActivity instance is held by DownloadTask and DownloadTask is hold by system. You will leak one activity instance.

For fixing this, you should change above code to:

publicclassMainActivityextendsActivity {

    @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        newDownloadTask(this).execute();
    }

    publicvoidshowInfo() {
    }
}

classDownloadTaskextendsAsyncTask<Void, Void, Void> {
    WeakReference<MainActivity> mainActivityWeakReference;

    publicDownloadTask(MainActivity activity) {
        mainActivityWeakReference = newWeakReference<MainActivity>(activity);
    }

    @OverrideprotectedVoiddoInBackground(Void... params) {
        returnnull;
    }

    @OverrideprotectedvoidonPostExecute(Void data) {
        if (mainActivityWeakReference.get() != null) {
            mainActivityWeakReference.get().showInfo();
        }
    }
}

In this case, when new MainActivity is created, the old one isn't held by DownloadTask (due to weak reference attribute), so the old one will be destroyed by Android Garbage Collector in future. You also should to check every time you use a weak reference object, because you don't know exactly when GC will destroyed those object.

Here is my own blog about another situation of memory leak. Memory leak when using static inner class

Hope this help.

Solution 2:

There are some case, if your fragment is set to retain instance, it'll be longer than activity, or if your fragment is leaked.

Post a Comment for "Weak Reference Instead Of Getactivity() (android Avoid Memory Leak)?"