es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Android – Jetpack – Hacer que la clase creada perezosamente sea consciente del ciclo de vida.

Tengo un caso interesante para resolver.

Antecedentes

Tengo un ViewModel que es un LifecycleObserver, sigo un buen patrón arquitectónico en el que este VM sirve la lógica global de la pantalla y compone VMs más pequeños dentro para servir a los componentes que están en la pantalla.

Para que estos VM más pequeños funcionen sin problemas, los hago conscientes del ciclo de vida en el onCreate del ViewModel del contenedor.

kotlin
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
smallerVMs.forEach(owner.lifecycle::addObserver)
}

Problema

Sin embargo, tengo n otros pequeños VMs que instanciaré según una llamada a API.

Como no tengo referencia de ellos hasta que se instancian, no puedo hacerlos conscientes del ciclo de vida en onCreate como se mencionó anteriormente. Y cuando la API regresa con resultados y los instancio, ¡no tengo conocimiento de la instancia de LifecycleOwner!

Pensé en cachear el LifecycleOwner en onCreate, pero eso significa mantener una referencia a la Vista en un VM, lo cual no es una buena práctica en MVVM.

¿Algún pensamiento al respecto?
Gracias de antemano!
Descargo de responsabilidad: tener los VM más pequeños dentro del gran VM es esencial, ya que los VM más pequeños son piezas de presentación reutilizables en toda la aplicación.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Solución posible

    Una manera de resolver este problema es utilizar un LifecycleObserver personalizado para las VMs más pequeñas que pueda manejar el caso en que el LifecycleOwner no esté disponible. Este observador personalizado puede usar un Handler para publicar las actualizaciones a las VMs más pequeñas cuando el LifecycleOwner esté disponible.

    Aquí hay un ejemplo de cómo se podría implementar:

    1. Cree un LifecycleObserver personalizado para las VMs más pequeñas que implemente Handler.Callback:
    class SmallViewModelObserver(private val handler: Handler) : LifecycleObserver, Handler.Callback {
    
        private val smallVMs = mutableListOf<smallviewmodel>()
    
        fun addViewModel(viewModel: SmallViewModel) {
            smallVMs.add(viewModel)
            handler.post {
                viewModel.lifecycle.addObserver(this)
            }
        }
    
        fun removeViewModel(viewModel: SmallViewModel) {
            smallVMs.remove(viewModel)
            viewModel.lifecycle.removeObserver(this)
        }
    
        override fun handleMessage(msg: Message): Boolean {
            if (msg.what == MSG_REGISTER_OBSERVERS) {
                for (viewModel in smallVMs) {
                    viewModel.lifecycle.addObserver(this)
                }
            }
            return true
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        private fun onCreate(owner: LifecycleOwner) {
            if (owner.lifecycle.currentState == Lifecycle.State.CREATED) {
                handler.post {
                    owner.lifecycle.addObserver(this)
                }
            }
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        private fun onDestroy(owner: LifecycleOwner) {
            owner.lifecycle.removeObserver(this)
            handler.removeCallbacksAndMessages(null)
        }
    
        companion object {
            const val MSG_REGISTER_OBSERVERS = 1
        }
    }
    
    1. En la ViewModel del contenedor, cree una instancia de SmallViewModelObserver y regístrela como un LifecycleObserver:
    class ContainerViewModel : ViewModel(), LifecycleObserver {
    
        private val handler = Handler(Looper.getMainLooper(), SmallViewModelObserver(handler = handler))
    
        private val smallVMs: List<smallviewmodel> = listOf()
    
        private val smallViewModelObserver: SmallViewModelObserver
            get() = handler.callback as SmallViewModelObserver
    
        override fun onCreate(owner: LifecycleOwner) {
            super.onCreate(owner)
    
            smallViewModelObserver.addViewModels(smallVMs)
        }
    
        fun onResult(result: List<smallviewmodel>) {
            smallVMs.addAll(result)
            handler.sendEmptyMessage(SmallViewModelObserver.MSG_REGISTER_OBSERVERS)
        }
    
        // ...
    }
    
    1. Cuando la lista de VMs más pequeñas esté disponible (p. ej., después de una llamada a la API), agréguelas al SmallViewModelObserver:
    val result = apiCall()
    val smallerVMs = result.map { SmallViewModel() }
    containerViewModel.onResult(smallerVMs)
    

    Este enfoque utiliza un Handler para publicar las actualizaciones a las VMs más pequeñas cuando el LifecycleOwner esté disponible. Esto permite que las VMs más pequeñas se agreguen al ciclo de vida incluso si el LifecycleOwner no está disponible en el momento de instanciarlas.

    Tenga en cuenta que este enfoque tiene algunas limitaciones y posibles inconvenientes:

    • El Handler puede introducir cierto retraso entre el momento en que el LifecycleOwner esté disponible y el momento en que las VMs más pequeñas se agreguen al ciclo de vida. Este retraso se puede mitigar utilizando un HandlerThread con alta prioridad.
    • El SmallViewModelObserver es responsable de realizar un seguimiento de las VMs más pequeñas y agregarlas al ciclo de vida. Esto puede hacer que el código sea más complejo y más difícil de mantener.
    • El SmallViewModelObserver puede mantener referencias a VMs más pequeñas que ya no se están utilizando. Esto se puede mitigar eliminando las VMs más pequeñas del observador cuando ya no sean necesarias.

Comments are closed.