如何使用@BindsInstance在Dagger 2中工作

20
我最近将dagger 2.8升级到了2.9版本并添加了以下内容的文档:
-添加了@BindsInstance以便于组件构建器轻松绑定在图形之外构造的实例。
-生产者:添加了ProducerMonitor.ready(),当生产者的所有输入可用时调用该方法。
-删除了@Provides(type=...)的使用。使用dagger.multibindings中的注解代替。同时也删除了@Produces.type
-现在验证了所有绑定方法,即使它们在特定的@Component中未被使用。
-@Component.dependencies不再能包含@Modules
我想知道这些新功能的作用是什么:
谢谢!!
注意: 我对dagger 2还不熟悉,但我希望能够充分利用这个库。
2个回答

44

@bindsInstance 用于从模块中移除构造函数并链接在获取组件时使用的模块。

没有 @BindsInstance

@Module
public class AppModule {

    private final Application application;

    public AppModule(Application application) {
        this.application = application;
    }

    @Provides
    @Singleton
    Application provideApplication() {
        return  application;
    }

    @Provides
    @Singleton
    public SharedPreferences providePreferences() {
        return application.getSharedPreferences("store",
                Context.MODE_PRIVATE);
    }
}

这些模块(ToastMakerModule 和 SensorControllerModule)是为了学习目的而设计的,它们会获取上下文并实例化,可能对于真实的示例不太实用。

public class ToastMaker {

    private Application application;

    public ToastMaker(Application application) {
        this.application = application;
    }

    public void showToast(String message) {
        Toast.makeText(application, message, Toast.LENGTH_SHORT).show();
    }
}

    @Module
    public class ToastMakerModule {

        @Singleton
        @Provides
        ToastMaker provideToastMaker(Application application) {
            return  new ToastMaker(application);

        }
   }

@Singleton
@Component(modules = {AppModule.class, ToastMakerModule.class, SensorControllerModule.class})
public interface AppComponent {
    void inject(MainActivity mainActivity);

    // DaggerAppComponent.build() returns this Builder interface

    @Component.Builder
    interface Builder {
        AppComponent build();

        Builder appModule(AppModule appModule);

        Builder sensorControllerModule(SensorControllerModule sensorControllerModule);

        Builder toastMakerModule(ToastMakerModule toastMakerModule);
    }

}

像这样构建组件

 appComponent = DaggerAppComponent
                .builder()
                .appModule(new AppModule(this))
                .sensorControllerModule(new SensorControllerModule())
                .toastMakerModule(new ToastMakerModule())
                .build();

使用@BindsInstance

@Module
public class AppModule {

    @Provides
    @Singleton
    public SharedPreferences providePreferences(Application application) {
        return application.getSharedPreferences("data",
                Context.MODE_PRIVATE);
    }
}

组件

@Singleton
@Component(modules = {AppModule.class, ToastMakerModule.class, SensorControllerModule.class})

public interface AppComponent {
    void inject(MainActivity mainActivity);

    @Component.Builder
    interface Builder {

        AppComponent build();


        // @BindsInstance replaces Builder appModule(AppModule appModule)
        // And removes Constructor with Application AppModule(Application)

        @BindsInstance
        Builder application(Application application);
    }
}

并且构建像这样的组件

   appComponent = DaggerAppComponent
                .builder()
                .application(this)
                .build();

你知道官方文档中的 @UserName 注解是从哪里来的吗?https://google.github.io/dagger/users-guide.html#binding-instances - Vairavan
你能说一下 Build 组件的部分应该放在哪里吗?我是新手。 - Arun
@Arun,我的意思是你使用下面的代码片段“构建组件”来构建组件,现在已经更改了。 - Thracian

1
@BindsInstance 允许组件直接托管依赖项,因此其生命周期与组件的生命周期相同。这可以用于避免使用 @Singleton 作用域。这真的很重要吗?避免单例作用域有助于 DaggerAppComponent 在不需要昂贵的 DoubleCheck 的情况下访问提供程序。因此,是的,仍然可以使用模块而不使用任何作用域。但是,使用模块仍意味着 DaggerAppComponent 将使用一个提供程序工厂来注入依赖项。使用 @BindsInstance,除非通过 Lazy<>Provider<> 惰性注入依赖项,否则根本不需要提供程序。
任何已知为正在创建的 AppComponent 的依赖项(如字符串常量等)都是 @BindsInstance 的良好候选项。请注意,这基于 Dagger 2.19。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接