Inject interfaces without provide methods on Dagger 2

Let’s say you are developing an Android app with MVP design pattern and you have created an interface for your presenter called HomePresenter. And right after that you have created an implementation for that interface which is called HomePresenterImp.

public interface HomePresenter {
Observable<List<User>> loadUsers();
}
public class HomePresenterImp implements HomePresenter { public HomePresenterImp(){ } @Override
public Observable<List<User>> loadUsers(){
//Return user list observable
}
}

We also need a Dagger module to provide this presenter class. We can’t just add @Inject to the constructor because we want to inject the interface, not the implementation. So our dagger module looks like this;

@Module
public class HomeModule {

@Provides
public HomePresenter providesHomePresenter(){
return new HomePresenterImp();
}
}

What if we need to add a depedency to the presenter implementation called UserService. That means, we have to add the UserService to the provider method in the module and pass that to the constructor of the HomePresenterImp. Also we have to add UserService as a field and constructor parameter in the HomePresenterImp.

Or….

We can just use @Binds annotation in module like this :

@Module
public abstract class HomeModule {

@Binds
public abstract HomePresenter bindHomePresenter(HomePresenterImp
homePresenterImp);
}

This says to the dagger that which implementation it should use when injecting the interface. You probably notice that this is an abstract class. That means we can add abstract methods.

The method signature says to the dagger that inject the HomePresenter interface(return parameter) by using HomePresenterImp(method parameter) implementation.

So adding just @Inject annotation to the constructor of the HomePresenterImp would be enough now.

We don’t need to add dependency parameters to the provide method anymore. We can simply use @Inject at constructor!

@PerActivity
public class HomePresenterImp implements HomePresenter {
private UserService userService; @Inject
public HomePresenterImp(UserService userService){
this.userService = userService;
} @Override
public Observable<List<User>> loadUsers(){
return userService.getUsers();
}
}

TL DR;

If you have provide methods which just call constructor of implementation classes to inject interfaces, use @Binds annotation instead to get rid of boilerplate code in your dagger module.

The (retired) Pub(lication) for Android & Tech, focused on Development