Skip to content
ArceApps Logo ArceApps
EN

MVVM View: UI Inteligente pero Pasiva en Android

3 min de lectura
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.

Share this post:

También te puede interesar

design.md: El Nuevo Estándar para el Diseño con IA
IA 13 de junio de 2026

design.md: El Nuevo Estándar para el Diseño con IA

Descubre cómo design.md complementa a agents.md, enfocándose en decisiones de diseño, UI/UX, accesibilidad y Jetpack Compose para el desarrollo Android en la era de los agentes de IA.

Leer más
Google Stitch: La Revolución del Diseño UI en Android con IA
IA 13 de junio de 2026

Google Stitch: La Revolución del Diseño UI en Android con IA

Descubre cómo Google Stitch, impulsado por Gemini, está transformando el diseño de interfaces en Android. Ejemplos, guías, trucos y su integración con Jetpack Compose y Kotlin.

Leer más
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 más