Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dagger 2 with Kotlin, returning type with generic in ApplicationComponent

I want to return type with generic to be exposed by sub-graphs, the problem is in auto-generated java-classes, I tried to do something, but the one way to solve it is to remove generic type from AppComponent and return simple object. Is there more "right" approach?

Here is the AppComponent

@Singleton
@Component(modules = arrayOf(ApplicationModule::class))
interface ApplicationComponent {
    fun inject(activity: BaseActivity<MvpView, MvpPresenter<MvpView>>)

    //...
    fun dataBase(): Database<Realm>
}

here is function in the ApplicationModule

@Provides @Singleton fun provideDatabase(@AppContext context: App): Database<Realm> {
    Realm.init(context)
    val config = RealmConfiguration.Builder()
            .deleteRealmIfMigrationNeeded()
            .name("db")
            .build()
    Realm.setDefaultConfiguration(config)
    return RealmDatabase(Realm.getDefaultInstance())
}

Then I want to receive my Database

@Provides @ActivityScope fun provideDich(database: Database<Realm>) = Someobject(database)

And then I see log that says:

**Error:com.test.data.storage.Database<? extends io.realm.Realm> cannot be provided without an @Provides-annotated method.**

Because dagger2 generates factories like this and there is java masks

    public final class Logout_Factory implements Factory<Logout> {
  private final MembersInjector<Logout> logoutMembersInjector;

  private final Provider<SessionStorage.CloudStorage> arg0Provider;

  private final Provider<Database<? extends Realm>> arg1Provider;

  public Logout_Factory(
      MembersInjector<Logout> logoutMembersInjector,
      Provider<SessionStorage.CloudStorage> arg0Provider,
      Provider<Database<? extends Realm>> arg1Provider) {
    assert logoutMembersInjector != null;
    this.logoutMembersInjector = logoutMembersInjector;
    assert arg0Provider != null;
    this.arg0Provider = arg0Provider;
    assert arg1Provider != null;
    this.arg1Provider = arg1Provider;
  }

  @Override
  public Logout get() {
    return MembersInjectors.injectMembers(
        logoutMembersInjector, new Logout(arg0Provider.get(), arg1Provider.get()));
  }

  public static Factory<Logout> create(
      MembersInjector<Logout> logoutMembersInjector,
      Provider<SessionStorage.CloudStorage> arg0Provider,
      Provider<Database<? extends Realm>> arg1Provider) {
    return new Logout_Factory(logoutMembersInjector, arg0Provider, arg1Provider);
  }
}
like image 948
Dennis Zinkovski Avatar asked Jan 10 '17 10:01

Dennis Zinkovski


1 Answers

I had the same problem and I found out the solution.

You need to declare the @JvmWildcard in your @Provide method return type.

@Provides 
@Singleton 
fun provideDatabase(@AppContext context: App): Database<@JvmWildcard Realm> {
    Realm.init(context)
    val config = RealmConfiguration.Builder()
            .deleteRealmIfMigrationNeeded()
            .name("db")
            .build()
    Realm.setDefaultConfiguration(config)
    return RealmDatabase(Realm.getDefaultInstance())
}
like image 86
Bisca Avatar answered Sep 28 '22 08:09

Bisca