Cómo establecer la propiedad de Kotlin tardía en nulo

La class de abajo tiene un ciclo de vida muy único, que me obliga a lateinit temporalmente las properties lateinit

 class SalesController : BaseController, SalesView { @Inject lateinit var viewBinder: SalesController.ViewBinder @Inject lateinit var renderer: SalesRenderer @Inject lateinit var presenter: SalesPresenter lateinit private var component: SalesScreenComponent override var state = SalesScreen.State.INITIAL //only property that I want to survive config changes fun onCreateView(): View { /** lateinit variables are set here */ } fun onDestroyView() { //lateinit variables need to be dereferences here, or we have a memory leak renderer = null!! //here's the problem: throws exception bc it's a non-nullable property 

}}

Así es como lo usa el marco.

 controller.onCreateView() //same instance of controller controller.onDestroyView() //same instance of controller controller.onCreateView() //same instance of controller controller.onDestroyView() //same instance of controller 

Mis properties lateinit se inyectan con daga, y debo configurarlas para que onDestroyView en onDestroyView , o tener una pérdida de memory. Sin embargo, esto no es posible en kotlin, hasta donde yo sé (sin reflexión). Podría hacer que estas properties sean nulables, pero eso vencería el propósito de la security nula de Kotlin.

No estoy muy seguro de cómo resolver esto. ¿Idealmente podría haber algún tipo de procesador de anotación que generaría código java para onDestroyView variables específicas automáticamente en onDestroyView ?

lateinit properties de lateinit usan null como un valor de indicador no inicializado, y no existe una manera clara de establecer null en el campo de respaldo de una propiedad de lateinit sin reflexión.


Sin embargo, Kotlin le permite anular el comportamiento de las properties usando properties delegadas. Parece que no hay ningún delegado que permita eso en kotlin-stdlib , pero si necesita exactamente este comportamiento, puede implementar su propio delegado para hacerlo, agregando algún código a sus utilidades:

 class ResettableManager { private val delegates = mutableListOf<ResettableNotNullDelegate<*, *>>() fun register(delegate: ResettableNotNullDelegate<*, *>) { delegates.add(delegate) } fun reset() { delegatesToReset.forEach { it.reset() } } } class Resettable<R, T : Any>(manager: ResettableManager) { init { manager.register(this) } private var value: T? = null operator fun getValue(thisRef: R, property: KProperty<*>): T = value ?: throw UninitializedPropertyAccessException() operator fun setValue(thisRef: R, property: KProperty<*>, t: T) { value = t } fun reset() { value = null } } 

Y el uso:

 class SalesController : BaseController, SalesView { val resettableManager = ResettableManager() @set:Inject var viewBinder: SalesController.ViewBinder by Resettable(resettableManager) @set:Inject var renderer: SalesRenderer by Resettable(resettableManager) @set:Inject var presenter: SalesPresenter by Resettable(resettableManager) fun onDestroyView() { resettableManager.reset() } } 

Creo que lo que necesitas es una propiedad normal que permita el nullable y saludable sin la madurez de lo lateinit :

 class SalesController : BaseController, SalesView { @Inject @JvmField var viewBinder: SalesController.ViewBinder? = null 

Con esta solución, el comstackdor le pedirá que verifique si viewBinder es null o no, pero IMO es apropiado aquí ya que puede ser null en cualquier punto de su progtwig.

  • ¿Qué es el doble explosión de Kotlin?
  • Error de compilation de la llamada insegura de Kotlin en un receptor nulo después de un control nulo
  • Manera idiomática de manejar lists anulables o vacías en Kotlin
  • Kotlin security nula?
  • ¿Cómo puedo crear una instancia de un object usando valores de parameters de constructor pnetworkingeterminados en Kotlin?
  • La mejor forma de comprobar null en kotlin?
  • ¿Cuándo debería usar let {} y cuando simplemente! = Null
  • manejar un object que puede devolver nulo en kotlin
  • Las comprobaciones nulas no se insertan para el tipo reificado cuando param no es nulo
  • Asignación variable de nula Kotlin
  • ¿Por qué la llamada insegura .run () funciona bien en un valor nulo en Kotlin?