Dagger 2 ContributesAndroidInjector proporciona actividad al module
Estoy tratando de encontrar una manera less rutinaria de implementar un ActivityModule
que se usa en todas las actividades de mi aplicación. Esta es mi configuration actual:
ActivityModule :
- Expresiones Lambda en Kotlin
- ¿Puedo mezclar Ktor con Exposed?
- Cómo convertir la salida de la function a la Unidad con Kotlin
- Kotlin: ¿Ya no es posible iterar un map con una input desestructurada? ¿Error?
- ListView.CHOICE_MODE_SINGLE reference no resuelta
@Module class ActivityModule(private val activity: Activity) { @Provides @ActivityScope fun providesActivity(): Activity = activity @Provides @ActivityContext @ActivityScope fun providesContext(): Context = activity @Provides @ActivityContext @ActivityScope fun providesLayoutInflater(): LayoutInflater = activity.layoutInflater @Provides @ActivityContext @ActivityScope fun providesResources(): Resources = activity.resources }
AppActivityModule (proporciona actividades para AndroidInjectionModule)
@Module(subcomponents = [ AppActivityModule.WelcomeActivityComponent::class ]) internal abstract class AppActivityModule { @Binds @IntoMap @ActivityKey(WelcomeActivity::class) abstract fun bindWelcomeActivityInjectorFactory(builder: WelcomeActivityComponent.Builder): AndroidInjector.Factory<out Activity> @ActivityScope @Subcomponent(modules = [(ActivityModule::class)]) interface WelcomeActivityComponent : AndroidInjector<WelcomeActivity> { @Subcomponent.Builder abstract class Builder : AndroidInjector.Builder<WelcomeActivity>() { abstract fun activityModule(myActivityModule: ActivityModule): AndroidInjector.Builder<WelcomeActivity> override fun seedInstance(instance: WelcomeActivity) { activityModule(ActivityModule(instance)) } } } }
Lo que quiero que sea AppActivityModule en su lugar es:
@Module internal abstract class AppActivityModule { @ContributesAndroidInjector(modules = [(ActivityModule::class)]) abstract fun contributeWelcomeActivityInjector(): WelcomeActivity }
Pero esto, bastante comprensible, me da un error /di/AppActivityModule_ContributeWelcomeActivityInjector.java:29: error: @Subcomponent.Builder is missing setters for requinetworking modules or subcomponents: [...di.modules.ActivityModule]
Mi pregunta es: ¿hay una manera less repetitiva de lograr lo que estoy tratando de hacer? Sé de @Bind
y @BindsInstance
(de esta respuesta ) pero parece que esto solo funciona si tengo un module por actividad y ato el tipo de actividad concreta que no quiero en este caso: quiero que ActivityModule
funcione con todos ocupaciones.
- No se puede save el model de datos que contiene List <Model> con Room ORM Kotlin
- Cómo resolver: Error: ejecución fallida para la tarea ': aplicación: kaptDebugKotlin'?
- ¿Cuál es el tipo de palabra key?
- ¿Qué es "implementación" en las dependencies de Kotlin Gradle?
- `break` y` continue` en `forEach` en Kotlin
- ¿Cuál es la forma correcta de usar una comparación "mayor que" o "menor que" en integers nulables en Kotlin?
- Obtener los elementos de una list de lists con la API de transmisión de Java en Kotlin
- Barra de navigation inferior "Fantasma" cuando el fragment se carga en la actividad del hogar
Una forma de minimizar el text estándar es hacer un ActivityModule genérico y luego crear un pequeño Módulo específico por Actividad. Perdona mi falta de experiencia en Kotlin, pero aquí va:
// Abstract class so you don't have to provide an instance @Module abstract class ActivityModule { // No need for ActivityScope: You're always binding to the same Activity, so // there's no reason to have Dagger save your Context instance in a Provider. @Binds @ActivityContext fun providesContext(activity: Activity): Context // This doesn't *have* to be in a companion object, but that way // Android can do a static dispatch instead of a virtual method dispatch. // If you don't need that, just skip the constructor arguments and make these // normal methods and you'll be good to go. companion object { @JvmStatic @Provides @ActivityContext fun providesLayoutInflater(activity: Activity): LayoutInflater = activity.layoutInflater @JvmStatic @Provides @ActivityContext fun providesResources(activity: Activity): Resources = activity.resources } }
Y tu module:
@Module internal abstract class AppActivityModule { @Module internal interface WelcomeActivityModule { // The component that @ContributesAndroidInjector generates will bind // your WelcomeActivity, but not your Activity. So just connect the two, // and suddenly you'll have access via injections of Activity. @Binds fun bindWelcomeActivity(activity: WelcomeActivity) : Activity } @ContributesAndroidInjector( modules = [ActivityModule::class, WelcomeActivityModule::class]) abstract fun contributeWelcomeActivityInjector(): WelcomeActivity }
Tenga en count que aunque esto funciona para Activity, Service, BroadcastReceiver y otros, es posible que no desee ser tan rápido con Fragment. Esto se debe a que dagger.android maneja las jerarquías de fragments con los fragments principales, por lo que desde un componente secundario puede tener acceso a YourApplication, YourActivity, YourParentFragment y YourChildFragment, y a todos sus componentes. Si algo en YourChildFragmentComponent depende de un Fragment no calificado, sería ambiguo si realmente quiere YourParentFragment o YourChildFragment. Dicho esto, este layout tiene sentido para las Actividades y ciertos Fragmentos, por lo que tiene sentido usarlo (con precaución).
- Spring Boot with AsyncRestTemplate Netty Client falla
- Construyendo un proyecto de Kotlin + Java 9 con Gradle