/ / Impossibile fornire una stringa qualificata con Dagger2: android, kotlin, dagger

Impossibile fornire una stringa qualificata con Dagger2 - android, kotlin, dagger

Sto cercando di seguire il campione Qui

Ho già usato Dagger2 con AndroidInjector con successo, ma ora stavo sperimentando il nuovo DaggerApplication e DaggerAppCompatActivity.

Ottengo l'errore:

Errore: (5, 1) errore: [dagger.android.AndroidInjector.inject (T)] java.lang.String non può essere fornito senza un costruttore @Inject o da un metodo @ Provides- o @ Produces-commentato.

Non penso che le nuove classi di Dagger stiano causando il problema. Se rimuovo il @DeviceModel in BuildModule.kt il codice viene compilato.

Qualche suggerimento?

Ecco il codice:

Il AppComponent.kt

@Component(modules = arrayOf(
AndroidSupportInjectionModule::class,
AppModule::class,
MainActivitySubComponent.MainActivityModule::class
))
interface AppComponent : AndroidInjector<App> {
@Component.Builder
abstract class Builder : AndroidInjector.Builder<App>()
}

Il AppModule.kt

@Module(subcomponents = arrayOf(MainActivitySubComponent::class))
class AppModule {

}

Il BuildModule.kt

@Module
class BuildModule {
@Provides
@DeviceModel
fun provideModel(): String {
return MODEL
}
}

Il DeviceModel.kt

@Qualifier
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class DeviceModel

Il MainActivitySubComponent.kt

@Subcomponent(modules = arrayOf(BuildModule::class))
interface MainActivitySubComponent : AndroidInjector<MainActivity> {

@Subcomponent.Builder
abstract class Builder : AndroidInjector.Builder<MainActivity>()

@Module(subcomponents = arrayOf(MainActivitySubComponent::class))
abstract class MainActivityModule {
@Binds
@IntoMap
@ActivityKey(MainActivity::class)
internal abstract fun bind(builder: MainActivitySubComponent.Builder): AndroidInjector.Factory<out Activity>
}
}

The * MainActivity.kt **

class MainActivity : DaggerAppCompatActivity() {
@Inject
@DeviceModel
lateinit var model: String

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(model, model);
}
}

Il App.kt

class App : DaggerApplication() {

override fun applicationInjector(): AndroidInjector<App> {
return DaggerAppComponent.builder().create(this)
}
}

risposte:

1 per risposta № 1

Quando usi Dagger con oggetti Kotlin, dobbiamo considerare come Kotlin crea effettivamente delle proprietà nella JVM.

@Inject
@DeviceModel
lateinit var model: String

Con una proprietà come questa, Kotlin compila tre elementi Java: un campo di supporto privato, un getter e un setter (a causa di var piuttosto che val). Senza ulteriori indizi sul tuo intento, Kotlin colloca il tuo DeviceModel annotazione sul getter.

La soluzione è specificare che il campo deve essere annotato con @field:[annotation].

@Inject
@field:DeviceModel
lateinit var model: String

Potrebbe anche essere necessario utilizzare @JvmField rendere pubblico il campo di supporto per Dagger, che precluderebbe l'utilizzo lateinite, naturalmente, richiede di inizializzare la stringa.

@Inject
@field:DeviceModel
@JvmField
var model: String

Aggiornare: Non sono sicuro del perché, ma nei miei test, il campo era privato, motivo per cui ho suggerito @JvmField. Secondo il Documentazione di Kotlin, il campo dovrebbe essere creato con la stessa visibilità del setter.


Nota che, in generale, Kotlin è abbastanza intelligente da applicare annotazioni personalizzate con @Target(AnnotationTarget.FIELD) al campo di supporto, ma questo ti impedirebbe di usarlo anche su fun providesModel