7

I'm trying to design a GCMHelper class. Essentially, the class is a singleton, and the Activity can request the singleton to setupGCM() as such.

GCMHelper.getInstance(MainActivity.this).setupGCM();

The setupGCM() method will just see if a GCM registration is necessary (e.g. app has no gcm, or app is updated needing a new gcm), and do nothing if a registration is not needed.

This is "ok" because my activity doesn't need to touch the GCM id value. Everything is handled in setupGCM() method of the singleton. setupGCM() happens in the background, so control goes right back to activity. No UI lag. GCM id generation happens fast, but I'm trying to account for the following error in the documentation.

public static final String ERROR_SERVICE_NOT_AVAILABLE

The device can't read the response, or there was a 500/503 from the server that can be retried later. The application should use exponential back off and retry.

So my setupGCM method will keep trying as of right now (5 times to be exact with a few seconds increasing between each delay between each retry). But what happens if the user presses back and calls finish() on said activity. Now the activity is finished, but the context is still saved with a singleton. This causes a memory leak no?

This would happen even if the GCMHelper wasn't a singleton. The reason it IS a singleton is so that the next time the activity gets created it can see if a regeneration retry is already in progress.

What happens if I pass it MainActivity.this.getApplicationContext() to the context needed for the singleton. Will that be better for the Activity because it will be allowed to be GC'd?

EGHDK
  • 17,818
  • 45
  • 129
  • 204
  • 1
    Yes, it will cause a memory leak. You can store the Context reference as a weak reference. – Zielony Jan 16 '15 at 17:06
  • 1
    Passing activity instance as context - yes, it will. Passing getApplicationContext() instance - potentially, but Application context usually stay alive during all VM instance lifetime. So if Application context is dead - your static class is dead class too. But if you need to use activity - you can use weak rederence. – Volodymyr Baydalka Jan 16 '15 at 17:07
  • @VolodymyrBaydalka what about passing in the Application context? I'm alright with the singleton trying to retry gcm as long as the GCM is running. I don't want to put it in a service, because I'm also alright with the application/process being killed and not finishing gcm registration. – EGHDK Jan 16 '15 at 17:13
  • @Zielony how would I do make my `private Context context'` a weak ref? – EGHDK Jan 16 '15 at 17:13
  • if you saw this? @EGHDK http://stackoverflow.com/questions/9809336/android-asyntask-use-weak-reference-for-context-to-avoid-device-rotate-screen – reidisaki Jan 16 '15 at 18:00

1 Answers1

0

Yes you will have a memory leak. You should use the application context. Check out this good article on Context http://possiblemobile.com/2013/06/context/

Quote : If this Context were an Activity, we would effectively hold hostage in memory all the views and other potentially large objects associated with it; creating a leak.

It even has an example for your case, using a Singleton :

public class CustomManager {
    private static CustomManager sInstance;

    public static CustomManager getInstance(Context context) {
        if (sInstance == null) {
            //Always pass in the Application Context
            sInstance = new CustomManager(context.getApplicationContext());
        }

        return sInstance;
    }

    private Context mContext;

    private CustomManager(Context context) {
        mContext = context;
    }
}
Gregriggins36
  • 905
  • 10
  • 20