What is the use case for @Binds vs @Provides annotation in Dagger2

前端 未结 2 1827
长发绾君心
长发绾君心 2020-12-15 04:45

I am not certain on the purpose for Dagger2\'s @Bind annotation.

From what i have read online im still not clear but here is an example:

@Module
pu         


        
相关标签:
2条回答
  • 2020-12-15 05:04

    @Binds can be perfectly equivalent to a @Provides-annotated method like this:

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

    ...though you'd probably prefer a variant that takes HomePresenterImp as a method parameter, which lets Dagger instantiate HomePresenterImp (assuming it has an @Inject constructor) including passing any dependencies it needs. You can also make this static, so Dagger doesn't need to instantiate your Module instance to call it.

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

    So why would you choose @Binds instead? Dagger has a FAQ about it, but it boils down do these reasons:

    • @Binds is (slightly) more compact: You can skip the implementation.
    • @Binds works in interfaces and abstract classes, which are strictly required for Dagger features like @BindsOptionalOf and @ContributesAndroidInjector.
    • @Binds helps your code stay efficient. @Provides methods can be instance methods, which require Dagger to instantiate your Module in order to call them. Making your @Provides method static will also accomplish this, but your @Provides method will still compile if you forget the static. @Binds methods will not.
    • @Binds prevents Dagger from having to codegen and keep a separate Factory/Provider for the object, since Java doesn't give Dagger access to know that the implementation is as simple as it is. In your case, Dagger can cast the Provider<HomePresenterImp> to a Provider<HomePresenter> and only keep one, rather than keeping one for HomePresenter that does nothing but call the one for HomePresenterImp.

    Thus, the entire thing would be well-represented as:

    @Binds abstract HomePresenter bindHomePresenter(HomePresenterImp presenter);
    
    0 讨论(0)
  • 2020-12-15 05:04

    Here a concrete case where you need Bind annotation, imagine you got a BaseActivityModule which is include in all your activity modules that provides your activity viewmodel.

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

    Here you see we need to provide an AppCompatActivity and a ViewModelProvider.Factory. You cannot provide AppCompatActivity with a Provide annotation since activities are created by android.

    We're assuming your concrete ActivityModule for example MainActivityModule will provide MainActivity class either because you create a MainActivity sub component or you used ContributesAndroidInjector to automatically create your sub components (but this is another talk).

    So we have our MainActivityModule providing MainActivity and our MainActivityModule includes our BaseActivityModule which need an AppCompatActivity. So here the Bind magic, let's tell Dagger that when you need an AppCompatActivity you can use our MainActivity.

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

    You can see more from my project template here

    0 讨论(0)
提交回复
热议问题