Saeed Masoumi Saeed Masoumi - 1 month ago 25
Android Question

Android Dagger 2 and MVP injecting inside an injected object

I want to use Dagger 2 with MVP pattern. So I have this scenario, each

View
has its own
Component
e.g.
MyFragment
has a component like this:

@PerFragment @Component(dependencies = ActivityComponent.class, modules = MyFragmentModule.class)
public interface MyFragmentComponent {
void inject(MyFragment fragment);
}


And in
MyFragmentModule
, I provided a presenter and a model which will be used in
MyFragment


@Module public class MyFragmentModule {

@Provides @PerFragment public MyPresenter providePresenter() {
return new MyPresenter();
}

@Provides @PerFragment public Model provideModel() {
return new Model();
}
}


Now I'm injecting component in
MyFragment
:

public class MyFragment extends Fragment{
@Inject MyPresenter presenter;

@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
component = DaggerMyFragmentComponent.builder()...build();
component.inject(this);
}
}


Also
MyPresenter
is look like this:

public class MyPresenter {

@Inject Model model;
}


Question

I don't know how to inject
Model
in my presenter. I don't want to injecting a component in my presenter like what i did in
MyFragment
.

Is there any way for this approach?

Answer

Considering field injection must be manually called through the component, you need a reference to your component. Of course, you shouldn't legitimately create a new component in your Presenter, I think what you ought to do is provide the class that holds the reference to the component.

@Module
public class MyFragmentModule {
    private MyFragment myFragment;

    public MyFragmentModule(MyFragment myFragment) {
        this.myFragment = myFragment;
    }

    @Provides
    public MyFragment myFragment() {
        return myFragment;
    }

    @Provides @PerFragment public MyPresenter providePresenter(MyFragment myFragment) {
        return new MyPresenter(myFragment);
    }

    @Provides @PerFragment public Model provideModel(MyFragment myFragment) {
        return new Model(myFragment);
    }        
}

public class MyPresenter {
    @Inject Model model;

    public MyPresenter(MyFragment myFragment) {
        myFragment.getComponent().inject(this);
    }
}

Your other alternative is constructor injection.

public class MyPresenter {
    private Model model;

    public MyPresenter(Model model) {
        this.model = model;
    }
}

    @Provides @PerFragment public MyPresenter providePresenter(Model model) {
        return new MyPresenter(model);
    }

EDIT: A third solution would be to skip module with your Presenter altogether, and just use @Inject annotated constructor.

@PerFragment
public class MyPresenter {
    private Model model;

    @Inject
    public MyPresenter(Model model) {
        this.model = model;
    }
 }

Or

@PerFragment
public class MyPresenter {
    @Inject
    Model model;

    @Inject
    public MyPresenter() {
    }
 }
Comments