Je ne suis pas certain du but de Dagger2 @ Bind annotation.
D'après ce que j'ai lu en ligne, je ne suis toujours pas clair, mais voici un exemple:
@Module
public abstract class HomeModule {
@Binds
public abstract HomePresenter bindHomePresenter(HomePresenterImp
homePresenterImp);
}
et les définitions de classe ressemblent à ceci:
public interface HomePresenter {
Observable<List<User>> loadUsers();
}
public class HomePresenterImp implements HomePresenter {
public HomePresenterImp(){
}
@Override
public Observable<List<User>> loadUsers(){
//Return user list observable
}
}
pourquoi aurais-je besoin d'utiliser @Binds si je peux simplement utiliser fournit une annotation comme suit:
@Provides
public HomePresenter provideHomePresenter() {
return new HomePresenterImp();
}
quel est le cas d'utilisation de @Binds au lieu de @Provides? si j'utilise @Binds, dois-je encore le déclarer dans mon composant d'application (c'est une classe abstraite lorsque j'utilise @Binds)?
@Binds peut être parfaitement équivalent à une méthode annotée @ Provides comme celle-ci:
@Provides
public HomePresenter provideHomePresenter() {
return new HomePresenterImp();
}
... bien que vous préfériez probablement une variante qui prend HomePresenterImp comme paramètre de méthode, ce qui permet à Dagger d'instancier HomePresenterImp (en supposant qu'il possède un constructeur @Inject), y compris en passant toutes les dépendances dont il a besoin. Vous pouvez également faire ceci static
, donc Dagger n'a pas besoin d'instancier votre instance de Module pour l'appeler.
@Provides
public static HomePresenter provideHomePresenter(HomePresenterImp presenter) {
return presenter;
}
Alors pourquoi choisiriez-vous @Binds
au lieu? Dagger a un FAQ à ce sujet , mais il se résume à ces raisons:
static
accomplira également cela, mais votre méthode @Provides sera toujours compilée si vous oubliez le static
. Les méthodes @Binds ne le seront pas.Provider<HomePresenterImp>
à un Provider<HomePresenter>
et n'en conserver qu'un, plutôt que d'en conserver un pour HomePresenter qui ne fait rien d'autre que d'appeler celui de HomePresenterImp.Ainsi, le tout serait bien représenté comme:
@Binds abstract HomePresenter bindHomePresenter(HomePresenterImp presenter);
Voici un cas concret où vous avez besoin d'une annotation Bind
, imaginez que vous avez un BaseActivityModule
qui est inclus dans tous vos modules d'activité et qui fournit votre modèle de vue d'activité.
@Module
object BaseActivityModule {
@Provides
@ActivityScope
@ActivityContext
@JvmStatic
fun provideViewModelProvider(
activity: AppCompatActivity,
viewModelFactory: ViewModelProvider.Factory
): ViewModelProvider = ViewModelProviders.of(activity, viewModelFactory)
}
Ici, vous voyez, nous devons fournir un AppCompatActivity
et un ViewModelProvider.Factory
. Vous ne pouvez pas fournir à AppCompatActivity
une annotation Provide
car les activités sont créées par Android.
Nous supposons que votre béton ActivityModule
par exemple MainActivityModule
fournira la classe MainActivity
soit parce que vous créez un sous-composant MainActivity soit parce que vous avez utilisé ContributesAndroidInjector
pour créer automatiquement votre sous-composants (mais ceci est un autre discours).
Nous avons donc notre MainActivityModule
fournissant MainActivity
et notre MainActivityModule
inclut notre BaseActivityModule
qui a besoin d'un AppCompatActivity
. Voici donc la magie de Bind
, disons à Dagger que lorsque vous avez besoin d'un AppCompatActivity
, vous pouvez utiliser notre MainActivity
.
@Module(includes = [BaseActivityModule::class])
abstract class MainActivityModule {
@Binds
@ActivityScope
abstract fun bindActivity(activity: MainActivity): AppCompatActivity
}
Vous pouvez voir plus de mon modèle de projet ici