Dagger 2 with Kotlin, returning type with generic

2019-04-08 20:23发布

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

1条回答
forever°为你锁心
2楼-- · 2019-04-08 21:02

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())
}
查看更多
登录 后发表回答