I use Dagger2 for DI in my android application. I found that I have to write inject method for every class that uses @Inject field. Is there a way that I can just inject the parent class so that I don't have to call inject on every subclass? Take Activity for example. I have a BaseActivity
that that every Activity extends from. Is there a way that I can just create an inject method in the component for BaseActivity and just call inject in BaseActivity's onCreate, and @inject fields in sub activities get injected automatically?
Constructor injection should be the main way that you do dependency injection. It's simple: A class needs something and thus asks for it before it can even be constructed. By using the guard pattern, you can use the class with confidence, knowing that the field variable storing that dependency will be a valid instance.
Types of Dependency Injection The injector class injects dependencies broadly in three ways: through a constructor, through a property, or through a method. Constructor Injection: In the constructor injection, the injector supplies the service (dependency) through the client class constructor.
DI does violate encapsulation, and this can be avoided.
To inject an object in the activity, you'd use the appComponent defined in your Application class and call the inject() method, passing in an instance of the activity that requests injection. When using activities, inject Dagger in the activity's onCreate() method before calling super.
I encountered the same situation. One way to ease a bit the injection from a common component in all Activities is the following:
1) Extend the Application class to be able to create the common component and keep a reference to it.
public class ApplicationDagger extends Application { private ApplicationComponent component; @Override public void onCreate(){ super.onCreate(); component = DaggerApplicationComponent.builder().applicationModule(new ApplicationModule(this)).build(); } public ApplicationComponent getComponent(){ return component; } }
2) Create an abstract DaggerActivity which gets the common component from Application and calls an abstract method injectActivity
, giving the component as an argument. Like this:
public abstract class DaggerActivity extends Activity { @Override public void onCreate(Bundle saved){ super.onCreate(saved); ApplicationComponent component = ((ApplicationDagger) getApplication()).getComponent(); injectActivity(component); } public abstract void injectActivity(ApplicationComponent component); }
3) Last, you have to actually inject each Activity
extending DaggerActivity
. But this can be done with less efforts now, as you have to implement the abstract
method otherwise you'll get compile errors. Here we go:
public class FirstActivity extends DaggerActivity { @Inject ClassToInject object; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //initialize your Activity } @Override public void injectActivity(ApplicationComponent component) { component.inject(this); } }
Of course, you still have to declare each Activity explicitly in your Component.
UPDATE : Injecting @ActivityScope objects into Fragments
At some point, I needed to use custom scopes to bind objects to an Activity
life cycle. I decided to extends this post as it might help some people.
Let's say you have a @Module class ActivityModule
and a @Subcomponent interface ActivityComponent
.
You would need to modify the DaggerActivity
. The Activities
extending DaggerActivity
would need to implement the new method (change of signature).
public abstract class ActivityDagger extends AppCompatActivity { ActivityComponent component; @Override protected void onCreate(Bundle savedInstanceState) { component = ((ApplicationDagger) getApplication()).getComponent().plus(new ActivityModule(this)); injectActivity(component); super.onCreate(savedInstanceState); } ActivityComponent getComponent() { return component; } public abstract void injectActivity(ActivityComponent component); }
Then, a class FragmentDagger
extending Fragment
can be created like this :
public abstract class FragmentDagger extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityDagger activityDagger = (ActivityDagger) getActivity(); ActivityComponent component = activityDagger.getComponent(); injectFragment(component); } public abstract void injectFragment(ActivityComponent component); }
As for the Activities
, the Fragments
extending FragmentDagger
have only one method to implement:
public abstract void injectFragment(ActivityComponent component);
You should be able to reuse Fragments
wherever you want. Notice that the method super.onCreated()
in ActivityDagger
should be called after the component instantiation. Otherwise, you will get NullPointerException when the Activity
state is recreated, because the method super.onCreate()
of the Fragment
will be called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With