1

I am trying to implement Architecture Components from Codelabs. But I'm getting the below error

Do not place Android context classes in static fields (static reference to FarmerNetworkDataSource which has field mContext pointing to Context); this is a memory leak (and also breaks Instant Run) less...

I used the code snippet directly from Google Codelabs. You can refer it here

I have seen some duplicate questions. But i can't figure out which is the best pratice to follow.

Please help & Guide me...

CODE

public class FarmerNetworkDataSource {

    // For Singleton instantiation
    private static final Object LOCK = new Object();
    private static FarmerNetworkDataSource sInstance;
    private final Context mContext;

    private final AppExecutors mExecutors;

    private FarmerNetworkDataSource(Context context, AppExecutors executors) {
        mContext = context;
        mExecutors = executors;
    }

    /**
     * Get the singleton for this class
     */
    public static FarmerNetworkDataSource getInstance(Context context, AppExecutors executors) {
        Log.d(LOG_TAG, "Getting the network data source");
        if (sInstance == null) {
            synchronized (LOCK) {
                sInstance = new FarmerNetworkDataSource(context.getApplicationContext(), executors);
                Log.d(LOG_TAG, "Made new network data source");
            }
        }
        return sInstance;
    }
}

REPOSITORY

public static FarmerRepository provideRepository(Context context) {
        AppExecutors executors = AppExecutors.getInstance();
        FarmerNetworkDataSource networkDataSource =
                FarmerNetworkDataSource.getInstance(context.getApplicationContext(), executors);
        return FarmerRepository.getInstance(networkDataSource, executors);
    }
Arulnadhan
  • 923
  • 4
  • 17
  • 46
  • Looking at the source from the github repository you have `WeatherNetworkDataSource networkDataSource = WeatherNetworkDataSource.getInstance(context.getApplicationContext(), executors);` What context are you passing to the constructor of `FarmerNetworkDataSource` activity context should not live longer than activity lifecycle – Raghunandan Oct 21 '17 at 17:31
  • @Raghunandan I have added the code where the DataSource is created – Arulnadhan Oct 22 '17 at 05:19
  • i downloaded the repo and running lint on the same. If you are using application context nothing to worry and also what context is used in provideRepository – Raghunandan Oct 22 '17 at 07:16
  • its a lint warning that you see. There is no leak in the repository code you linked to. You can use leak canary https://github.com/square/leakcanary and look for memory leaks in your code – Raghunandan Oct 22 '17 at 07:32
  • That's not an error, it's a warning! We are programmers, we ignore warnings! – 0xC0DED00D Dec 08 '17 at 14:15
  • Possible duplicate of [Warning: Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)](https://stackoverflow.com/questions/37709918/warning-do-not-place-android-context-classes-in-static-fields-this-is-a-memory) – TT-- Jul 17 '19 at 13:43

1 Answers1

3

My way around it is:

private static WeakReference<Context> appContext;

public static Context getAppContext() {
    if (appContext == null)
        return null;
    return appContext.get();
}

WeakReference influences the garbage collector. Most objects that are referenced must be kept in memory until they are unreachable. But with WeakReference, objects that are referenced can be collected.

I used it in a couple of projects and it proved to be very handy.

Simon
  • 2,643
  • 3
  • 40
  • 61