Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should Context be injected with Dagger?

I know it is possible to inject Context with Dagger. We can see examples here and here.

On the other end, there are numerous posts about not placing context on a static variable to avoid leaks. Android Studio (lint) also warms about this:

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

I understand that by injecting a Context with Dagger, we are placing it on a singleton class, so context is somehow static. Doesn't this go against the lint warning?

Injecting the context seems to create cleaner code, since you don't have to pass it to several classes (that don't need it) so that they can further pass it to other classes that need it for some reason (getting a resource for instance).

I am just concerned that this may cause some undesired leak or breaks lint in some way.

like image 779
fhsilva Avatar asked Mar 08 '23 22:03

fhsilva


2 Answers

You should never store/reference activity context (an activity is a context) for longer than the lifetime of the activity otherwise, as you rightly say, your app will leak memory. Application context has the lifetime​ of the app on the other hand so is safe to store/reference in singletons. Access application context via context.getApplicationContext().

like image 161
Pete Hendry Avatar answered Mar 23 '23 11:03

Pete Hendry


If you are aware of Android lifecycles and are careful to distinguish the Application Context and the Context of Activities and Services then there is no fault injecting the Context using Dagger 2.

If you are worried about the possibility of a memory leak you can use assertions to prevent injection of the wrong Context:

public class MyActivityHelper {
     private final Context context;

     @Inject
     public MyActivityHelper (Context context) {
         if (context instanceof Application) {
              throw new IllegalArgumentExecption("MyActivityHelper requires an Activity context");
         }
     }
}

Alternatively you could use Dagger 2 Qualifiers to distinguish the two so you don't accidentally inject an app Context where an Activity Context is required. Then your constructor would look something like this:

@Inject
public class MyActivityHelper (@Named("activity") Context context) {

Note also, as per David's comment, a Dagger 2 @Singelton is not necessarily a static reference.

like image 39
David Rawson Avatar answered Mar 23 '23 10:03

David Rawson