Currently in my codebase I have the following class(part of it) where it shows me 2 memory leaks with the message " Do not place Android context classes in static fields (static reference to Myclass which has field context pointing to Context); this is a memory leak (and also breaks Instant Run)" I am not sure what the alternative is. Is this a 100% memory leak ? I get the leak warning on "INSTANCE;" and "static" declaration for context. Any idea how to go about fixing it?
public enum Myclass {
INSTANCE;
public static final boolean TLS_ENABLED = true;
private static final String TAG = Myclass.class.getSimpleName();
private static final String SP = "My_class";
private static Context context;
public void init(Context context, String appKey, String appSecret) {
init(context, null, appKey, appSecret);
}
/**
* Initialize class
*
* @param context Application level context.
* @param apiUrl API url of backend server
* @param appKey Application key
* @param appSecret Application secret
* @throws IllegalArgumentException If activity instance will be passed as the context
* @throws IllegalArgumentException If application key is empty or null
* @throws IllegalArgumentException If application secret is empty or null
*/
public void init(Context context, String apiUrl, String appKey, String appSecret) {
if (null == context) { throw new NullPointerException(); }
if (!(context instanceof Application)) { throw new IllegalArgumentException("Supply my class with application context"); }
// if (TextUtils.isEmpty(apiUrl)) { throw new IllegalArgumentException("Api url can't be null or empty string"); }
if (TextUtils.isEmpty(appKey)) { throw new IllegalArgumentException("App key can't be null or empty string"); }
if (TextUtils.isEmpty(appSecret)) { throw new IllegalArgumentException("App secret can't be null or empty string"); }
this.apiUrl = apiUrl;
this.appKey = appKey;
this.appSecret = appSecret;
this.sp = context.getSharedPreferences(SP, Context.MODE_PRIVATE);
MyClass.context = context;
initManagers();
}
/**
* Initializes managers. This method must be called after constructor
* returns, as the managers during own initialization may use myclass.get()
* method.
*/
private void initManagers() {
accountManager = new AccountManager();
myclassApi = new MyclassApi(context, apiUrl);
contactManager = new ContactManager();
connectionManager = new ConnectionManager();
meetingListManager = new MeetingListManager();
}
/**
* Returns {@link Context} that was passed to
* {@link myclass#init(Context, String, String)}.
*
* @return
*/
public static Context getContext() {
return context;
}
/**
* Returns {@link SharedPreferences} instance.
*
* @return SharedPreferences
*/
public SharedPreferences getSp() {
return this.sp;
}
public static class Event<T> {
private State state = State.SUCCESS;
private Throwable t;
private T data;
private String errorMessage;
/**
* Event state. If event related to network request/response
* operations - state indicates the physical (not logical)
* success or fail of request.
*/
public enum State {
/**
* Indicates that attempt to get data or perform task successful
*/
SUCCESS,
/**
* Indicates that attempt to get data or perform task fails,
* and reason of fail is the incorrect request data
*/
FAIL,
/**
* Indicates that attempt to get data or perform task encounter an error
* mostly due to connection problem
*/
ERROR,
/**
* Indicates that attempt to get data or perform task was ignored
* according to internal state of event producer.
*/
IGNORED
}
}
It's safe to store application context in a static field, you can simple call context.getApplicationContext()
on any context reference you get before storing it in a static field.
The application context is a singleton anyway and you cannot leak it.