Dagger2:如何在同一个模块中使用@Provides和@Binds

14 android dagger-2

我正在使用新的Dagger2(版本2.11),我正在使用像AndroidInjector和的新功能ContributesAndroidInjector.我有一个活动子组件,

        @Module
        abstract class ActivityBuilderModule {
            @ContributesAndroidInjector(modules = 
                   {UserListModule.class, MainFragmentModule.class})
            @ActivityScope
            abstract MainActivity bindsMainActivity();

        }



  @Module
  public abstract class MainFragmentModule {
    @ContributesAndroidInjector
    @FragmentScope
    @FragmentKey(UserListFragment.class)
    abstract UserListFragment bindsUserListFragment();

}
Run Code Online (Sandbox Code Playgroud)

UserListModule为片段提供依赖关系.一些依赖项我只想绑定实例,并返回,就像

 @Binds
 @ActivityScope
 abstract UserListView mUserListView(UserListFragment userListFragment);
Run Code Online (Sandbox Code Playgroud)

而不仅仅是简单地返回依赖,就像

@Provides
@ActivityScope
UserListView mUserListView(UserListFragment userListFragment){
    return userListFragment;
}
Run Code Online (Sandbox Code Playgroud)

我的模块也包含一些@Provides方法.我们可以同时使用@Binds,并@Provides在同一模块中的方法呢?我尝试如下所示

        @Module
        public abstract class UserListModule {
            @Provides
            @ActivityScope
            UserListFragment mUserListFragment() {
                return new UserListFragment();
            }

            @Binds
            @ActivityScope
            abstract UserListView mUserListView(UserListFragment userListFragment);

           // other provides and binds methods...
           ......
           .....

        }
Run Code Online (Sandbox Code Playgroud)

这是它的投掷错误

Error:(22, 8) error: dagger.internal.codegen.ComponentProcessor was unable to process this interface because not all of its dependencies could be resolved. Check for compilation errors or a circular dependency with generated code.

有没有办法做到这一点?

Jef*_*ica 24

@Binds@ContributesAndroidInjector方法必须是抽象的,因为它们没有方法体.这意味着他们必须继续使用接口或抽象类.@Provides方法可能是static,这意味着它们可以继续使用抽象类和Java-8编译的接口,但非静态("实例")@Provides方法不适用于抽象类.这在Dagger常见问题解答中明确列出了"为什么不能@Binds和实例@Provides方法进入同一个模块?"部分."我该怎么做?" .

如果您的@Provides方法不使用实例状态,则可以标记它static,并且它可以转到与您的@Binds方法相邻的抽象类.如果不是,可以考虑使结合象@Binds@ContributesAndroidInjector成一个单独的类-有可能是静态的嵌套类-和包括使用includes的匕首的属性@Module注解.


gor*_*tya 15

以上Jeff的解决方案的一点点补充:

你可以创建内部接口而不是静态内部类,如下所示:

@Module(includes = AppModule.BindsModule.class)
public class AppModule {
    // usual non-static @Provides
    @Provides
    @Singleton
    Checkout provideCheckout(Billing billing, Products products) {
        return Checkout.forApplication(billing, products);
    }
    // interface with @Binds
    @Module
    public interface BindsModule {
        @Binds
        ISettings bindSettings(Settings settings);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 除了删除抽象关键字样板外,使用接口而不是抽象类是否有优势/劣势? (3认同)

Lev*_*yan 11

如果您在 kotlin 世界,另一种选择是利用 companion object

@Module
abstract class MyDaggerModule {

    @Binds
    abstract fun provideSomething(somethingImpl: SomethingImpl): Something

    companion object {

        @Provides
        fun provideAnotherThing(): AnotherThing {
            return AnotherThing()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)