Search code examples
androidgarbage-collectionweak-referencescontext-switching

Do we need to handle weak reference and context switching?


To mitigate memory leaks we keep a weak reference of an activity in an inner class running on different thread. We check weakreference.get() is non null and then only proceed further. What if when we checked weakreference.get() was non null but garbage collection happened, do we need to check if the reference is non null again and again or am I missing something?

public class MainActivity extends Activity {    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new MyAsyncTask(this).execute();
    }    
    private static class MyAsyncTask extends AsyncTask {
        private WeakReference<MainActivity> mainActivity;    
        
        public MyAsyncTask(MainActivity mainActivity) {   
            this.mainActivity = new WeakReference<>(mainActivity);            
        }       
        @Override
        protected Object doInBackground(Object[] params) {
            return doSomeStuff();
        }        
        @Override
        protected void onPostExecute(Object object) {
            super.onPostExecute(object);
            if (mainActivity.get() != null){
                //do something
                //context switching and garbage collection happen
                //again do a null check?
            }
        }
    }
}

Solution

  • What you should do is this:

    MainActivity temp = mainActivity.get();
    if (temp != null){
        // Use 'temp' to access the `MainActivity`
    }
    

    Assuming that temp is not null, the fact that you now have a regular reference for the MainActivity object in a live variable means that the object is strongly reachable. The garbage collector won't collect it.

    (Indeed, the GC won't break your WeakReference so long as temp is still reachable. The specs state that the GC will not break the ref in a (reachable) Reference if the target of the ref is strongly reachable.)


    But the flip-side is that if you don't have a strong reference to the MainActivity then the GC could break the WeakReference at any time. So, you should always check the result of the get() call.