Saltar al contenido principal
A
ArceApps

MVVM View: UI Inteligente pero Pasiva en Android

calendar_today
MVVM View: UI Inteligente pero Pasiva en Android

🎭 Teoría: El Rol de la Vista

En MVVM, la View (Activity, Fragment o Composable) tiene una única responsabilidad: Reflejar el estado del ViewModel.

No toma decisiones. No calcula nada. No sabe de dónde vienen los datos. Es un espejo.

Principio de Pasividad

Una View ideal debería ser tan “tonta” que si le pasas un estado con texto “Error 404”, lo muestre felizmente en verde si así está estilado, sin cuestionar si tiene sentido.

🔄 Unidirectional Data Flow (UDF)

El concepto clave para una View moderna es el flujo unidireccional.

  1. State (Down): El estado fluye hacia abajo, desde el ViewModel a la View.
  2. Events (Up): Los eventos fluyen hacia arriba, desde la View al ViewModel.
   ViewModel
      │   ▲
State │   │ Events (clicks)
      ▼   │
     View

Por qué UDF es superior

  • Predecibilidad: Solo hay una forma de cambiar la UI (cambiando el estado en el VM).
  • Debuggability: Si la UI está mal, sabes que el error está en el estado emitido, no en un método setText() perdido en un listener.

📱 Implementación: Compose vs XML

En Jetpack Compose (La Era Moderna)

Compose fue diseñado pensando en UDF.

@Composable
fun LoginScreen(
    // 1. State Hoisting: Recibe estado y lambdas
    uiState: LoginUiState,
    onLoginClick: (String, String) -> Unit
) {
    Column {
        TextField(
            value = uiState.username,
            // 2. No actualiza su propia variable. Manda evento.
            onValueChange = { /* Evento al VM (opcional) */ }
        )
        
        Button(
            // 3. Evento puro hacia arriba
            onClick = { onLoginClick(uiState.username, "pass") }
        ) {
            Text("Entrar")
        }
        
        if (uiState.isLoading) {
            CircularProgressIndicator()
        }
    }
}

En XML / Views (El Legado)

En el sistema clásico, debemos forzar este comportamiento observando flujos.

class LoginFragment : Fragment() {
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // Setup Listeners (Events Up)
        binding.loginButton.setOnClickListener {
            viewModel.onLoginClicked(binding.username.text.toString())
        }
        
        // Setup Observers (State Down)
        viewLifecycleOwner.lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState.collect { state ->
                    render(state)
                }
            }
        }
    }
    
    // Función pura de renderizado
    private fun render(state: LoginUiState) {
        binding.progressBar.isVisible = state.isLoading
        binding.loginButton.isEnabled = !state.isLoading
        
        if (state.error != null) {
            showError(state.error)
        }
    }
}

⚠️ Anti-Patrones Comunes en la View

1. Lógica Condicional en la UI

❌ Mal:

if (user.age > 18) {
    showBeerIcon()
}

Esto es lógica de negocio. Si mañana la edad legal cambia a 21, tienes que buscar en todos los XML/Composables.

✅ Bien:

// ViewModel
val showBeer: Boolean = user.age > 18

// View
if (state.showBeer) {
    showBeerIcon()
}

2. ViewModel manipulando la View

❌ Mal: Pasar la View al ViewModel.

viewModel.doSomething(binding.myTextView)

Esto destruye MVVM y crea memory leaks. El VM nunca debe importar android.view.*.

3. Crear Estado Local Duplicado

Si tienes un var isChecked en tu Composable y también un isChecked en tu ViewModel, tienes dos fuentes de verdad. Eventualmente se desincronizarán. Usa siempre el estado del ViewModel como única fuente de verdad (Single Source of Truth).

🎯 Conclusión

La View es la cara de tu aplicación, pero no debe ser el cerebro. Mantén tus vistas pasivas, reactivas y tontas. Si sigues estrictamente el Flujo Unidireccional de Datos, verás que bugs complejos de “estado inconsistente” desaparecen mágicamente.

Artículos relacionados

MVVM ViewModel: El Cerebro de la Operación
Android 4 de octubre de 2025

MVVM ViewModel: El Cerebro de la Operación

Profundiza en el componente ViewModel: Gestión de estado, ciclo de vida, corrutinas y cómo evitar los errores más comunes de diseño.

Leer artículo arrow_forward
MVVM Model: La Capa de Datos Invisible pero Vital
Android 2 de octubre de 2025

MVVM Model: La Capa de Datos Invisible pero Vital

El 'Model' en MVVM es mucho más que clases de datos. Aprende a diseñar una capa de modelo robusta que sobreviva a cambios de UI y backend.

Leer artículo arrow_forward
Arquitectura MVVM en Android: Guía Completa desde Cero
Android 1 de octubre de 2025

Arquitectura MVVM en Android: Guía Completa desde Cero

Domina el patrón Model-View-ViewModel desde los conceptos básicos hasta implementaciones avanzadas con ejemplos prácticos de un juego de Buscaminas para Android.

Leer artículo arrow_forward