Jetpack Compose: fundamentos, funciones Composable y State

Autor: IT Sectr Publicado: 2026-02-21 Tiempo de lectura: 8 min

Jetpack Compose es un framework declarativo de UI moderno de Google para el desarrollo de Android, lanzado en su versión estable 1.0 en julio de 2021. Compose reemplaza el diseño XML imperativo y el sistema View con funciones Kotlin anotadas con @Composable. Según Google I/O (2025), Compose se utiliza en el 55% de los nuevos proyectos de Android, y el tamaño promedio del código de UI se reduce entre un 30 y 50% en comparación con XML. El framework redibuja automáticamente solo las partes modificadas de la pantalla cuando cambia el State, eliminando llamadas manuales a notifyDataSetChanged o findViewById.

Puntos clave

  • Jetpack Compose — framework declarativo de UI de Google para Android en Kotlin (funciones @Composable en lugar de diseño XML).
  • @Composable — anotación de función que describe una parte de la UI, capaz de aceptar parámetros y leer State.
  • State y MutableState — mecanismo de reactividad: cuando State cambia, Compose recompone solo las funciones Composable dependientes.
  • remember — función de caché para valores entre recomposiciones; sin ella State se reinicia en cada actualización.
  • Modifier — cadena de configuraciones (padding, size, clickable, background) que controla la apariencia y el comportamiento de un Composable.

¿Qué es Jetpack Compose?

Jetpack Compose es un framework de UI de Google construido sobre principios de programación reactiva. En lugar de Activity con diseño XML, FragmentManager y ViewBinding, el desarrollador describe la interfaz mediante funciones Kotlin anotadas con @Composable. Compose no utiliza LayoutInflater — la UI son funciones Kotlin puras compiladas a bytecode. El framework consta de varias bibliotecas: Compose UI (componentes básicos Text, Button, Column, Row), Compose Foundation (Material Design, Gestures, Focus), Compose Material3 (Material You con Dynamic Colors) y Compose Runtime (State, Side Effects, Coroutines). Compose funciona en Android API 21+ (Android 5.0) y es totalmente compatible con código View/XML existente mediante ComposeView, un adaptador AndroidView.

Compose vs View System

View System (2008) utiliza una jerarquía de objetos View con gestión manual: el desarrollador crea un diseño XML, encuentra Views mediante findViewById, implementa un Adapter para RecyclerView y llama a notifyDataSetChanged cuando los datos cambian. Compose describe la UI de forma funcional: cuando el estado cambia, el framework recompone solo las funciones Composable modificadas, calcula el diff y aplica cambios mínimos al Canvas. El rendimiento de Compose es comparable al de View System, y en escenarios con listas complejas (LazyColumn) a menudo supera a RecyclerView al omitir elementos innecesarios mediante el parámetro key. En IT Sectr, Compose se utiliza para nuevos módulos de aplicaciones Android con minSdk 24+.

Funciones Composable: bloques de construcción de UI

@Composable — una anotación que convierte una función Kotlin normal en un bloque de construcción de UI. Las funciones Composable pueden llamar a otras funciones Composable, formando un árbol de componentes. A diferencia de View, las funciones Composable no tienen estado por defecto — son stateless y se redibujan en cada cambio de parámetros de entrada o State. El Compose Compiler transforma las funciones @Composable en código que puede ser interrumpido y reanudado (positional memoization), lo que permite a Compose reiniciar solo las partes modificadas sin reconstruir completamente el árbol.

kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun UserProfile(name: String, avatarUrl: String) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        AsyncImage(
            model = avatarUrl,
            contentDescription = "User avatar",
            modifier = Modifier.size(48.dp)
        )
        Spacer(modifier = Modifier.width(12.dp))
        Text(
            text = name,
            style = MaterialTheme.typography.titleMedium
        )
    }
}

La función UserProfile acepta name y avatarUrl como parámetros, construye una fila con un avatar y un nombre. Modifier.fillMaxWidth() estira el componente a todo el ancho, .padding(16.dp) añade relleno. MaterialTheme.typography.titleMedium utiliza el estilo de sistema Material 3. Cuando los parámetros name o avatarUrl cambian, Compose recompone UserProfile — recreando el componente con nuevos valores.

State y Recomposition en Jetpack Compose

State en Compose es cualquier valor cuyo cambio desencadena la recomposición (reinicio) de funciones @Composable dependientes. El enfoque básico es mutableStateOf(), que crea un MutableState<T> con soporte del sistema de snapshot de Compose. Snapshot es un mecanismo de seguimiento de cambios: cuando se escribe State, Compose marca el Snapshot actual como dirty, y el planificador de recomposición reinicia solo las funciones Composable que leen ese State. Para colecciones observables use mutableStateListOf() y mutableStateMapOf(). Compose admite State de componentes Lifecycle-Aware mediante collectAsState() para Kotlin Flow y observeAsState() para LiveData.

kotlin
@Composable
fun LikeButton() {
    var liked by remember { mutableStateOf(false) }
    var count by remember { mutableStateOf(42) }
    
    Button(
        onClick = {
            liked = !liked
            if (liked) count++ else count--
        },
        colors = ButtonDefaults.buttonColors(
            containerColor = if (liked) MaterialTheme.colorScheme.primary
                else MaterialTheme.colorScheme.surfaceVariant
        )
    ) {
        Text("♥ $count")
    }
}

El código crea un botón "Like" con estado liked (Boolean) y count (Int) almacenados mediante mutableStateOf(). Al presionar, liked se invierte y el contador aumenta/disminuye — Compose recompone LikeButton automáticamente. El delegado by permite usar State como una variable normal: liked = !liked en lugar de liked.value = !liked.value. El color del botón cambia reactivamente entre primary (me gusta) y surfaceVariant (no me gusta).

remember: caché entre recomposiciones

remember — una función de Compose que almacena en caché un valor entre recomposiciones. Sin remember, cada reinicio de una función Composable crea un nuevo estado (mutableStateOf) — esto rompe la lógica de la aplicación: al rotar la pantalla o cambiar el State padre, el contador se reinicia. remember acepta una lambda calculadora y computa el valor solo en la primera composición; en las siguientes devuelve el resultado en caché. Para reiniciar la caché use remember(key) — la clave determina cuándo recalcular el valor. remember(key1, key2) recalcula cuando cualquier clave cambia. Para estados de larga duración (que sobreviven a la rotación de pantalla) use rememberSaveable — un análogo de remember que guarda en Bundle mediante SavedStateHandle.

kotlin
@Composable
fun TimerScreen() {
    var seconds by rememberSaveable { mutableStateOf(0) }
    
    LaunchedEffect(Unit) {
        while (true) {
            delay(1000)
            seconds++
        }
    }
    
    Column(
        modifier = Modifier.fillMaxSize().padding(32.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            text = "Elapsed: ${seconds}s",
            style = MaterialTheme.typography.displayMedium
        )
    }
}

rememberSaveable conserva seconds al rotar la pantalla (cambio de configuración). LaunchedEffect inicia una corrutina que incrementa seconds cada segundo. En la recomposición de TimerScreen (cada segundo) seconds no se reinicia gracias a rememberSaveable. Use remember normal para estados que no deben sobrevivir cambios de configuración (por ejemplo, banderas de animación).

Modifier: cadena de configuraciones Composable

Modifier — un objeto contenedor inmutable que implementa el patrón Builder para configurar la apariencia, el comportamiento y el diseño de componentes Composable. Cada llamada a un método de Modifier (.padding(), .width(), .clickable(), .background()) devuelve un nuevo Modifier con el elemento añadido. El orden de los modificadores importa: .padding(16.dp).clickable { } — el relleno se aplica antes del manejador de clic, clickable rastrea toda el área incluyendo el relleno. .clickable { }.padding(16.dp) — toda el área antes del relleno es cliqueable, el relleno desplaza el contenido hacia adentro. Modifier admite implementaciones personalizadas mediante then(otherModifier) y compositionLocal para acceder a configuraciones padre.

kotlin
@Composable
fun CardExample() {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp)
            .clickable { println("Card clicked") },
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surfaceVariant
        )
    ) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text("Jetpack Compose", style = MaterialTheme.typography.titleLarge)
            Spacer(modifier = Modifier.height(8.dp))
            Text(
                "UI declarativa para Android con State y Modifier",
                style = MaterialTheme.typography.bodyMedium
            )
        }
    }
}

CardExample demuestra la cadena Modifier: fillMaxWidth + padding + clickable. Card es un componente Material3 con su propia configuración de elevation y colors. El Column anidado tiene un relleno interno de 16dp. Compose Material3 adapta automáticamente los colores a Dynamic Color (Material You) en Android 12+. Card es uno de los más de 30 componentes Material3 integrados en Compose.

State hoisting y arquitectura de Compose

State hoisting — un patrón de elevar el estado fuera de una función Composable hacia su llamador, haciendo la función stateless. Un componente stateless recibe datos y callbacks a través de parámetros sin poseer State por sí mismo. Esto mejora la reutilización y la testabilidad: el componente puede ser llamado con diferentes States y probado en preview. Google recomienda la arquitectura: ViewModel + StateFlow (o MutableStateFlow) + collectAsState() en Compose. ViewModel eleva el estado al nivel de pantalla, Compose lo renderiza. Los efectos secundarios (LaunchedEffect, DisposableEffect) manejan eventos únicos.

ComponenteResponsabilidadTecnología
ViewModelAlmacenamiento de State, lógica de negocioStateFlow, MutableStateFlow
Screen ComposableOrganización de pantalla, State hoistingcollectAsState(), Scaffold, LazyColumn
Stateless ComponentUI sin estado, renderizado puroParámetros @Composable + lambdas
Side EffectAcciones únicas (snackbar, navegación)LaunchedEffect, SnackbarHostState

Preguntas frecuentes

¿En qué se diferencia Jetpack Compose del diseño XML?

El diseño XML es imperativo: LayoutInflater carga XML, findViewById encuentra Views, el desarrollador actualiza manualmente texto/listas. Compose es declarativo: la UI se describe con funciones Kotlin @Composable, y el framework redibuja automáticamente solo las partes modificadas cuando State cambia. Compose reduce el volumen de código de UI entre un 30 y 50% y no utiliza XML.

¿Necesito una biblioteca separada para la navegación en Compose?

Sí, Google proporciona Navigation Compose — una biblioteca para navegación declarativa entre pantallas. NavController gestiona la pila de rutas, composable() registra pantallas, navArgument pasa parámetros. Alternativas: Voyager (community) y Decompose (Badoo). Navigation Compose es el estándar oficial con soporte para deep links y argumentos type-safe.

¿Qué es Modifier en Jetpack Compose?

Modifier es un contenedor inmutable de patrones de decoración (padding, size, clickable, background, border, clip) aplicados a componentes Composable. Cada llamada devuelve un nuevo Modifier con el elemento añadido. El orden importa: .padding().clickable() aplica relleno antes del clic, .clickable().padding() — al contrario. Modifier es la forma principal de personalizar componentes Compose.

¿Compose funciona en todas las versiones de Android?

Jetpack Compose admite Android API 21+ (Android 5.0 Lollipop) a través del Compose Compiler y Compose BOM. Material 3 (Dynamic Colors) está disponible en Android 12+; en versiones anteriores se usa una paleta fallback. Para proyectos nuevos, Google recomienda minSdk 24+ (Android 7.0), que está totalmente cubierto por Compose.

¿Cómo probar componentes Compose?

Google proporciona Compose UI Test — una biblioteca para pruebas en JVM (Desktop) y emulador. Funciones clave: composeTestRule.setContent { } para renderizar un componente, onNodeWithText() para encontrar elementos, performClick()/performTextInput() para acciones. Las pruebas Espresso son compatibles con Compose mediante ComposeTestRule, pero Compose UI Test es el enfoque preferido y más rápido.

Resumen

  • Jetpack Compose — framework declarativo de UI de Google para Android con funciones Kotlin @Composable en lugar de XML (estable desde 2021).
  • @Composable — anotación que convierte una función Kotlin en un componente de UI; el árbol de funciones Composable reemplaza la jerarquía View.
  • State y mutableStateOf — la base de la reactividad de Compose mediante el sistema Snapshot; la recomposición afecta solo a las funciones dependientes.
  • remember almacena en caché un valor entre recomposiciones; rememberSaveable preserva State en cambios de configuración.
  • Modifier — una cadena de configuraciones (padding, size, clickable, background) que forma un contenedor inmutable; el orden de los modificadores importa.
  • State hoisting — un patrón de elevar el estado hacia arriba para componentes stateless; ViewModel + StateFlow + collectAsState() es la arquitectura recomendada.
  • Material 3 con Dynamic Colors (Android 12+) es el tema estándar de Compose con adaptación automática al fondo de pantalla del dispositivo.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también