Search code examples
androiddata-bindingpicassodagger-2android-binding-adapter

Inject into Databinding Adapter with Dagger 2


I am using Android Databinding adapter and it says, it have to be static. So I am trying to make it non static and inject my classes into it with Dagger by following this tutorial. Although I can use my Picasso instance which is provided by dagger normally in app, it says Picasso cannot be provided without an @Inject constructor or an @Provides-annotated method.

I add @Inject annotation to my binding adapter constructor but still get same error

public class ImageBindingAdapter {

    private final Picasso picasso;

    @Inject
    public ImageBindingAdapter(Picasso picasso) {
        this.picasso = picasso;
    }

    @BindingAdapter("android:src")
    public void loadImage(ImageView view, String url) {
        picasso.load(url).fit().into(view);
    }
}

I thought the problem might be relevant about a component issue and changed my approach and followed this link and use subcomponent. But this time dagger can not generate subcomponent and I can not set it like in the example

// Build dagger binding subcomponent and set it like default databinding component 
        DataBindingUtil.setDefaultComponent(sApplicationComponent
                .daggerBindingComponentBuilder()
                .build());

How can I inject my custom classes into binding adapter with Dagger, any help is appreciated

Here is my dagger classes, it is pretty same from tutorial that I mentioned above

ImageBindingAdapter Class

public class ImageBindingAdapter {

    private final Picasso picasso;

    @Inject
    public ImageBindingAdapter(Picasso picasso) {
        this.picasso = picasso;
    }

    @BindingAdapter("android:src")
    public void loadImage(ImageView view, String url) {
        picasso.load(url).fit().into(view);
    }
}

BindingModule class

@Module
public class BindingModule {

    @Provides 
    @DataBinding
    ImageBindingAdapter provideImageBindingAdapter(Picasso picasso) {
        return new ImageBindingAdapter(picasso);
    }
}

BindingComponent class

@DataBinding
@Component(dependencies = AppComponent.class, modules = BindingModule.class)
public interface BindingComponent extends DataBindingComponent {

}

AppComponent class

@Singleton
@Component(modules = {AndroidSupportInjectionModule.class, AppModule.class, ...})
public interface AppComponent extends AndroidInjector<MyApp> {

    @Component.Builder
    interface Builder {

        @BindsInstance
        Builder application(Application application);
        AppComponent build();

    }

    @Override
    void inject(MyApp instance);
}

AppModule class

@Module
public class AppModule {

    @Singleton
    @Provides
    Picasso picasso(Application application, OkHttp3Downloader okHttp3Downloader) {
        return new Picasso.Builder(app.getApplicationContext())
                .downloader(okHttp3Downloader)
                .indicatorsEnabled(true)
                .build();
    }

     ....

}

Application class

    public class MyApp extends DaggerApplication {

        @Override
        protected AndroidInjector<MyApp> applicationInjector() {

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

            appComponent.inject(this);

            BindingComponent bindingComponent = DaggerBindingComponent.builder()
                .appComponent(appComponent)
                .build();
             DataBindingUtil.setDefaultComponent(bindingComponent);

            return appComponent;
        }
    }

Solution

  • As error said, dagger could not resolve Picasso dependency. In your case, the problem is that differenct dagger components can use directly only those dependencies, that interface marked with @Component annotation declared using methods. To allow AppComponent share Picasso with BindingComponent you need modify app component like that:

    @Singleton 
    @Component(modules = {AndroidSupportInjectionModule.class, AppModule.class, ...}) 
    public interface AppComponent extends AndroidInjector<MyApp> { 
        ...
        Picasso getPicasso();
    }
    

    After that dagger can properly resolve Picasso dependency and error should disappear.