Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning: Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)

Android Studio:

Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)

So 2 questions:

#1 How do you call a startService from a static method without a static variable for context?
#2 How do you send a localBroadcast from a static method (same)?

Examples:

public static void log(int iLogLevel, String sRequest, String sData) {     if(iLogLevel > 0) {          Intent intent = new Intent(mContext, LogService.class);         intent.putExtra("UPDATE_MAIN_ACTIVITY_VIEW", "UPDATE_MAIN_ACTIVITY_VIEW");         mContext.startService(intent);     } } 

or

        Intent intent = new Intent(MAIN_ACTIVITY_RECEIVER_INTENT);         intent.putExtra(MAIN_ACTIVITY_REQUEST_FOR_UPDATE, sRequest));         intent.putExtra(MAIN_ACTIVITY_DATA_FOR_VIEW, sData);         intent.putExtra(MAIN_ACTIVITY_LOG_LEVEL, iLogLevel);         LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent); 

What would be the correct way to do this without using mContext?

NOTE: I think my main question might be how to pass context to a class from which the calling method lives.

like image 325
John Smith Avatar asked Jun 08 '16 18:06

John Smith


1 Answers

Just make sure you pass context.getApplicationContext() or call getApplicationContext() on any context that is passed in via methods/constructor to your singleton if you decide to store it in any member field.

idiot proof example (even if someone would pass in an activity it will grab the app context and use that to instantiate the singleton):

public static synchronized RestClient getInstance(Context context) {     if (mInstance == null) {         mInstance = new RestClient(context.getApplicationContext());     }     return mInstance; } 

getApplicationContext() according to the docs: "Return the context of the single, global Application object of the current process."

It means that the context returned by "getApplicationContext()" will live through the entire process and thus it does not matter if you store a static reference to it anywhere since it will always be there during the runtime of your app (and outlive any objects/singletons instantiated by it).

Compare that to the context inside of views/activities holding large amounts of data, if you leak a context held by an activity, the system won't be able to free that resource which obviously is not good.

A reference to an activity by its context should live the same life cycle as the activity itself, otherwise it will hold the context hostage causing a memory leak (which is the reason behind the lint warning).

EDIT: To the guy bashing the example from the docs above, there's even a comment section in the code about what I just wrote about:

    // getApplicationContext() is key, it keeps you from leaking the     // Activity or BroadcastReceiver if someone passes one in. 
like image 72
Marcus Gruneau Avatar answered Oct 03 '22 07:10

Marcus Gruneau