En la biblioteca de Injekt para Kotlin, ¿cómo creo ámbitos locales, como para cada actividad de Android?
En la documentation de Injekt en Github, dice que existen ámbitos, pero no está claro cómo puedo usarlos para crear un scope local para cada actividad de Android, que tienen sus propias fábricas e instancias, pero también pueden usar algunas de un scope principal.
La variable Injekt
parece ser un ámbito global, y veo InjektScope
e InjektScopeMain
pero no hay ejemplos de cómo usarlos ni cómo se vinculan con los ámbitos principales. La única forma que veo es crear instancias de InjektScope
separadas y llamarlas, O llamar a Injekt
como un scope global. Esto funciona, pero es torpe.
- findViewById ClassCastExcpetion
- KotlinJS: ¿Cuándo usaría el tipo dynamic Kotlin?
- Error de Kotlin: Dagger no admite inyección en campos privados
- Kotlin: ¿Qué es kotlin.String! tipo
- Parámetro de conflicto de visibilidad efectiva entre java y kotlin
No hay una forma obvia de vincular, anidar, delegar o henetworkingar.
¿Esto es compatible, y si es así cómo?
Nota: esta pregunta fue escrita y respondida intencionalmente por el autor ( Preguntas de respuesta automática ), de modo que las respuestas idiomáticas a los temas comúnmente solicitados de Injekt + Kotlin están presentes en SO. Otras respuestas también son bienvenidas, ¡hay otros styles de cómo hacer esto! Divulgación, soy el autor de la biblioteca Injekt.
- Recyclerview: escucha los events de clic de relleno
- ¿Cómo compartir los mismos constructores en diferentes classs también conocidas como definir constructores en una interfaz?
- Kotlin: ¿Cómo verificar si enum contiene una cadena dada sin interferir con las excepciones?
- Llame a getMeasunetworkingWidth () o getWidth () para RecyclerView return 0 en data binding
- ¿Es posible usar doReturn () y CALLS_REAL_METHODS con mockito-kotlin?
- Señal / evento AboutToQuit en Android
- ¿Cómo accedo a un método estático de Java en una subclass de Kotlin?
- ¿Cómo hacer reference a una lambda desde adentro?
ACTUALIZACIÓN: Esto ahora está documentado en Injekt README
Es apoyado por la delegación de fábricas entre los ámbitos. Primero, algunos antecedentes:
Injekt permite el scope manual de las instancias en loggings de Injekt separados. El logging global, disponible a través de la variable Injekt
, es solo un scope creado previamente para usted. También puedes crear nuevos:
val myLocalScope: InjektScope = InjektScope(DefaultRegistrar())
Esto crea un ámbito independiente que no tiene ninguna relación con el mundo o con otros.
Pero luego puede vincular ámbitos creando fábricas en el nuevo ámbito que delegue parte de la creación de instancias en otro ámbito. Por ejemplo, el myLocalScope
mencionado anteriormente podría delegar algunas de las fábricas al scope global de Injekt
:
// delegate some factories to global Injekt instance myLocalScope.addSingletonFactory { Injekt.get<SomeSingletonClass>() } myLocalScope.addFactory { Injekt.get<SomeMultiValueClass>() }
Al delegar fábricas como esta, cualquier instancia multivalor no será almacenada en caching por ningún scope, ya que esas fábricas crean nuevas instancias en cada llamada. Para los singletons y las fábricas con key, los objects se almacenan en caching y existirá una reference a esos objects tanto en el ámbito local como en el delegado para cualquier instancia solicitada durante su ciclo de vida.
También puede usar múltiples ámbitos de forma independiente sin vincular ni delegar. Obtener algunas instancias desde un ámbito local, otras desde el global. Pero debe usar cada ámbito de forma independiente y tener cuidado de utilizar accidentalmente la variable global Injekt
cuando no esté previsto.
Si tiene fábricas comunes necesarias en ámbitos locales, puede crear fácilmente un descendiente de InjektScope
que las registre durante su construcción.
class MyActivityScope: InjektScope(DefaultRegistrar()) { init { // override with local value addSingletonFactory { SomeSingletonClass() } // import other registrations from defined modules importModule(OtherModuleWithPrepackagedInjektions) // delegate to global scope: addSingletonFactory { Injekt.get<SomeOtherSingleton>() } } } // then in each place you want a local scope val localScope = MyActivityScope() // later use the scope val singly: SomeSingletonClass = localScope.get() val other: SomeOtherSingleton = localScope.get()
O usando el mismo model que InjektMain
cree un descendiente de InjektScopedMain
que anule la function de fun InjektRegistrar.registerInjectables() { ... }
, si prefiere ser consistente con los modules. Por ejemplo:
class MyActivityModule: InjektScopedMain(InjektScope(DefaultRegistrar())) { override fun InjektRegistrar.registerInjectables() { // override with local value addSingletonFactory { NotLazy("Fnetworkingdy") } // import other registrations from defined modules importModule(OtherModuleWithPrepackagedInjektions) // delegate to global scope: addSingletonFactory { Injekt.get<SomeOtherSingleton>() } } } // then in each place you want a local scope val localScope = MyActivityModule().scope
Y aún puede usar properties delegadas, siempre que el scope se declare antes de su uso en el delegado:
val myProp: SomeClass by localScope.injectValue()
Puede usar la class base LocalScoped
para tener versiones locales de injectValue()
e injectLazy()
para hacerlo más conveniente cuando se inyectan miembros (vea el código para LocalScoped
). De esta forma, su syntax se mantiene constante (ver ejemplo en las testings ).
Para borrar un scope local, suelte su reference al scope y se saveá todo. No hay un método explícito claro.
Para get un enlace / delegación / inheritance más avanzado y más automático, consulte Injekt Github Issue # 31 y brinde comentarios sobre esta posible function futura.
Para el caso de uso de tener otras classs, henetworkingar el mismo ámbito local cuando se inyectan en la class que declara el ámbito local, consulte Injekt Github Issue # 32
- ¿Cuál es el objective pnetworkingeterminado para una anotación al anotar properties en Kotlin?
- ¿Podemos definir nuestros accesadores sin un valor init?