Dagger2中@Binds与@Provides批注的用例是什么

时间:2018-10-01 08:07:58

标签: android dagger-2

我不确定Dagger2的@Bind annotation.的目的

根据我在网上阅读的内容,我仍然不清楚,但这是一个示例:

@Module
public abstract class HomeModule {

  @Binds
  public abstract HomePresenter bindHomePresenter(HomePresenterImp   
    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
    }
}

如果我只能使用提供注释,为什么我需要使用@Binds:

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

@Binds而不是@Provides的用例是什么?如果我使用@Binds,我是否仍需要在我的appcomponent中声明它(当我使用@Binds时,它是一个抽象类)?

2 个答案:

答案 0 :(得分:5)

@Binds可以完全等同于@Provides注释的方法,如下所示:

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

...尽管您可能更喜欢使用HomePresenterImp作为方法参数的变体,该变体允许Dagger实例化HomePresenterImp(假设它具有@Inject构造函数),包括传递所需的任何依赖项。您也可以创建此static,因此Dagger无需实例化Module实例即可调用它。

@Provides
public static HomePresenter provideHomePresenter(HomePresenterImp presenter) {
    return presenter;
}

那为什么要选择@Binds呢? Dagger has a FAQ about it,但归结为以下原因:

  • @Binds(略)更紧凑:您可以跳过实现。
  • @Binds在接口和抽象类中工作,而@BindsOptionalOf和@ContributesAndroidInjector等Dagger功能则严格要求这些接口和抽象类。
  • @Binds帮助您的代码保持高效。 @Provides方法可以是实例方法,需要Dagger实例化您的Module才能调用它们。使您的@Provides方法static也可以完成此操作,但是如果您忘记了static,您的@Provides方法仍将编译。 @Binds方法不会。
  • @Binds防止Dagger进行代码生成并为该对象保留单独的Factory / Provider,因为Java不允许Dagger访问其实现是多么简单。在您的情况下,Dagger可以将Provider<HomePresenterImp>强制转换为Provider<HomePresenter>,并且只保留一个,而不是为HomePresenter保留一个,而只为HomePresenterImp调用一个。

因此,整个事情可以很好地表示为:

@Binds abstract HomePresenter bindHomePresenter(HomePresenterImp presenter);

答案 1 :(得分:2)

在一个具体的情况下,您需要Bind注释,假设您有一个BaseActivityModule,它包含在提供活动视图模型的所有活动模块中。

@Module
object BaseActivityModule {
    @Provides
    @ActivityScope
    @ActivityContext
    @JvmStatic
    fun provideViewModelProvider(
        activity: AppCompatActivity,
        viewModelFactory: ViewModelProvider.Factory
    ): ViewModelProvider = ViewModelProviders.of(activity, viewModelFactory)
}

在这里您看到我们需要提供一个AppCompatActivity和一个ViewModelProvider.Factory。由于活动是由android创建的,因此无法为AppCompatActivity提供Provide注释。

我们假设您的具体ActivityModule例如MainActivityModule将提供MainActivity类,因为您创建了MainActivity子组件,或者您使用了ContributesAndroidInjector自动创建了子组件(但这是另一回事)。

因此,我们有MainActivityModule提供了MainActivity,而我们的MainActivityModule包括了BaseActivityModule,需要一个AppCompatActivity。因此,在这里Bind的魔力,让我们告诉Dagger,当您需要AppCompatActivity时,可以使用我们的MainActivity

@Module(includes = [BaseActivityModule::class])
abstract class MainActivityModule {
    @Binds
    @ActivityScope
    abstract fun bindActivity(activity: MainActivity): AppCompatActivity
}

您可以从我的项目模板here

中看到更多内容