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.

Enviar datos del repositorio al modelo de vista en la arquitectura MVVM

¡Estoy confundido/a acerca de cómo usar la arquitectura MVVM! En algunos tutoriales, LiveData se guarda en un repositorio y luego se pasa al ViewModel. En muchos otros, LiveData se define dentro de una función del repositorio y se pasa al ViewModel utilizando el resultado de la función. Pero Google dice:

Puede resultar tentador trabajar con objetos LiveData en la capa de datos, pero LiveData no está diseñado para manejar flujos asíncronos de datos. …….. Si necesitas usar flujos de datos en otras capas de tu aplicación, considera usar Kotlin Flows y luego convertirlos a LiveData en el ViewModel utilizando asLiveData(). …. Para bases de código creadas con Java, considera usar Executors en conjunto con callbacks o RxJava.

Prefiero usar las coroutines o Flows de Kotlin. Pero no sé si en mi caso realmente es necesario o no. Estoy trabajando en una aplicación de chat. Cuando se recibe un mensaje, se llama a un escuchador en el repositorio y se recibe la información del mensaje en él. (El escuchador se ejecuta en un hilo en segundo plano) Ahora quiero enviar el objeto de mensaje al ViewModel y agregarlo a un LiveData que almacene la lista de mensajes.

object ChatsRepo {

fun listen(socket: Socket) {
    socket.on(Config.ON_MESSAGE, onMessage)
}

fun sendMessage(socket: Socket, json: String) {
    socket.emit(Config.ON_MESSAGE, json)
}

private val onMessage = Emitter.Listener { args: Array<any> ->
    // Este objeto de mensaje debe enviarse al ViewModel
    val message = Gson().fromJson(args[0].toString(), Message::class.java)
}

}

Puedo hacer esto fácilmente utilizando la función de orden superior:

object ChatsRepo {

lateinit var listener: (Message) -> Unit

private val onMessage = Emitter.Listener { args: Array<any> ->
    val message = Gson().fromJson(args[0].toString(), Message::class.java)
    listener(message)
}

}

¿Pero es mejor usar las coroutines o Flows de Kotlin? En casos similares, a veces es necesario enviar una lista al ViewModel.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    La arquitectura MVVM (Modelo-Vista-ViewModel) está diseñada para separar preocupaciones y mejorar la testabilidad en aplicaciones de Android. Cuando se trata de utilizar LiveData en la arquitectura MVVM, hay diferentes enfoques que se pueden tomar, pero es importante tener en cuenta que LiveData no debe ser utilizado en la capa de datos para manejar flujos asíncronos de datos.

    Según la documentación de Google, si necesitas utilizar flujos de datos en otras capas de tu aplicación, considera usar los Flows de Kotlin y luego convertirlos a LiveData en el ViewModel usando asLiveData().

    En el ejemplo de código proporcionado, el ChatsRepo escucha los mensajes entrantes y los recibe en la devolución de llamada onMessage, que se ejecuta en el hilo de fondo. Para enviar el objeto de mensaje recibido al ViewModel y añadirlo a un LiveData que almacena la lista de mensajes, se puede seguir el siguiente enfoque:

    object ChatsRepo {
    
        private val _messageFlow = MutableStateFlow<message?>(null)
        val messageFlow: Flow<message?> = _messageFlow.asStateFlow()
    
        private val onMessage = Emitter.Listener { args: Array<any> ->
            val message = Gson().fromJson(args[0].toString(), Message::class.java)
            // Añadir el mensaje al flujo
            _messageFlow.value = message
        }
    
        // Función para empezar a escuchar los mensajes entrantes
        fun listen(socket: Socket) {
            socket.on(Config.ON_MESSAGE, onMessage)
        }
    
        // Función para enviar un mensaje
        fun sendMessage(socket: Socket, json: String) {
            socket.emit(Config.ON_MESSAGE, json)
        }
    }
    

    En el ViewModel, se debe recolectar el messageFlow y añadir los mensajes al LiveData que almacena la lista de mensajes:

    class ChatsViewModel : ViewModel() {
    
        private val _messagesLiveData = MutableLiveData<><message>>()
        val messagesLiveData: LiveData<><message>> = _messagesLiveData
    
        init {
            viewModelScope.launch {
                ChatsRepo.messageFlow.collect { message ->
                    // Añadir el mensaje recibido a la lista de mensajes
                    message?.let { message ->
                        _messagesLiveData.value = _messagesLiveData.value.orEmpty().plus(message)
                    }
                }
            }
        }
    }
    

    Utilizando este enfoque, los mensajes se reciben en un flujo que se recolecta en el ViewModel. Los mensajes recibidos se añaden a la lista de mensajes almacenada en el LiveData, el cual puede ser observado por la interfaz de usuario.

    Sin embargo, si hay casos en los que se necesita enviar una lista al ViewModel, se recomienda utilizar las coroutines o los Flows de Kotlin para manejar el flujo de datos asíncronos, tal como sugiere la documentación de Google.</message?></message?>

Comments are closed.