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 № 1Quando 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 lateinit
e, 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