Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how it works @BindsInstance dagger 2

I have recently updated dagger 2.8 to 2.9 dagger. and documentation of the last release have been added as follows:

-Added @BindsInstance for component builders to easily bind instances that are constructed outside of the graph.

-Producers: Added ProducerMonitor.ready (), which is called when all of a producer's inputs are available.

-Removed @Provides(type =...) usage. Use the annotations in dagger.multibindings instead. @Produces.type was also removed.

-All binding methods are now validated, even if they are unused in a particular @Component

-@Component.dependencies can no longer include @Modules.

I want to know how these new features:

Thank you!!

Note: I am new to dagger 2, but you want to be able to make maximum use of this library.

like image 273
Juanes30 Avatar asked Feb 07 '17 04:02

Juanes30


2 Answers

@bindsInstance is used for removing constructor from module and chaining modules where you get component.

Without @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);
    }
}

These modules(ToastMakerModule, and SensorControllerModule) are for learning purposes they get context and instantiate , may not be practical for real examples

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);
    }

}

Build component like this

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

With @BindsInstance

@Module
public class AppModule {

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

Component

@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);
    }
}

and build component like this

   appComponent = DaggerAppComponent
                .builder()
                .application(this)
                .build();
like image 51
Thracian Avatar answered Sep 25 '22 12:09

Thracian


@BindsInstance lets the component host the dependency directly and hence the lifetime is the lifetime of the component. This can be used to avoid @Singleton scope. Does it even matter? Avoiding singleton scope helps DaggerAppComponent access the provider without a costly DoubleCheck. So yes, it is possible to still use the module and not use any scopes. However, using module still means that DaggerAppComponent is going to use a Provider factory to inject the dependency. Using @BindsInstance, the provider is not needed at all unless the dependency is injected lazily via Lazy<> or Provider<>.

Any dependencies (like String constants etc) that is known as AppComponent is being created are good candidates for @BindsInstance. Note this is based on Dagger 2.19.

like image 32
Vairavan Avatar answered Sep 22 '22 12:09

Vairavan