Jetpack Compose: qué es, conceptos clave y funciones Composable

Autor: IT Sectr Publicado: 2026-05-01 Tiempo de lectura: 9 min

Jetpack Compose es un toolkit declarativo moderno para construir interfaces de Android en Kotlin. El desarrollador describe la UI mediante funciones composable, y el toolkit redibuja automáticamente solo las partes que cambiaron. Según Android Developers (2026), Jetpack Compose funciona en Android 5.0 (API 21) y superior, es compatible con Material Design 3 y alcanza 120 FPS en dispositivos de gama media gracias a su propio sistema de Recomposition — un inteligente algoritmo diff que actualiza solo los widgets modificados.

Puntos clave

  • Jetpack Compose — un framework de UI declarativo para Android donde la interfaz se construye mediante funciones anotadas @Composable en Kotlin.
  • Recomposition — un mecanismo que actualiza automáticamente solo los componentes cuyos datos cambiaron, proporcionando 120 FPS.
  • State se gestiona mediante mutableStateOf, collectAsState y StateFlow — al cambiar el valor, la composición se reinicia para las vistas dependientes.
  • Modifier — una cadena de funciones para configurar rellenos, tamaños, fondo, clics y animaciones sin herencia de clases.
  • Side Effects — LaunchedEffect, DisposableEffect y rememberCoroutineScope — gestionan acciones secundarias: temporizadores, solicitudes de red, suscripciones.

¿Qué es Jetpack Compose?

Jetpack Compose es un framework declarativo de Google para construir interfaces de usuario de Android, anunciado en 2019 y que alcanzó su versión estable en 2021. A diferencia del antiguo View System (maquetación XML + Activity/Fragment), Compose utiliza funciones Kotlin anotadas — @Composable. La interfaz se describe completamente en Kotlin: no hay separación entre XML y código. Esto eliminó la clase de errores relacionados con la discrepancia de IDs en XML y Kotlin (type-safe synthetic no ayudaba en la refactorización).

Compose está construido sobre su propio sistema de renderizado — Canvas, no vinculado a la jerarquía de View. Cada Composable se dibuja directamente en Canvas, sin pasar por onMeasure/onDraw de View System. Esto proporciona un aumento de rendimiento en pantallas complejas: en las pruebas de Google (2023), una pantalla en Compose con 200 elementos se renderizó un 40% más rápido que una similar en RecyclerView + ViewHolder.

Requisitos mínimos y compatibilidad

Compose requiere minSdk 21 (Android 5.0) y Kotlin 1.9+. El BOM (Bill of Materials) de Compose sincroniza las versiones de todas las librerías de Compose. El framework es compatible con código existente de View System: Compose se integra mediante ComposeView en maquetaciones XML, y las View antiguas mediante AndroidView en la jerarquía de Compose. Según Google Play Console (2025), Android 5.0+ cubre el 97% de los dispositivos activos, por lo que la compatibilidad no es una limitación para la mayoría de los proyectos.

Funciones Composable y composición

@Composable es una anotación que convierte una función Kotlin normal en un bloque de construcción de UI. Una función Composable describe cómo debería verse un fragmento de la interfaz — texto, botón, lista. En lugar de devolver un valor, la función emite componentes UI en la composición. Es similar a un generador: cada función añade elementos a la pantalla al ser llamada.

kotlin
@Composable
fun ProfileCard(name: String, avatarUrl: String) {
    Card(
        modifier = Modifier.fillMaxWidth().padding(16.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surface
        )
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            AsyncImage(
                model = avatarUrl,
                contentDescription = "Avatar",
                modifier = Modifier.size(48.dp).clip(CircleShape)
            )
            Spacer(Modifier.width(12.dp))
            Text(
                text = name,
                style = MaterialTheme.typography.titleMedium
            )
        }
    }
}

La función ProfileCard recibe parámetros (name, avatarUrl) y emite Card → Row → AsyncImage + Text. Composición es el árbol de componentes emitidos en un solo pase. Si los parámetros no han cambiado, Compose omite la llamada a la función (recomposition skip). Si solo cambió name, solo se llamará a Text, el resto de elementos no se redibujarán. Esta recomposición inteligente es la ventaja clave de rendimiento de Compose frente a la optimización manual de View System.

Slots y Content Lambda

Las funciones Composable utilizan activamente slots — trailing lambda, content: @Composable (() -> Unit). Esto permite crear contenedores: Card, Column, Row aceptan una lambda content, y el contenido se inserta en el slot. La Slot API reemplazó atributos XML como android:layout_gravity — ahora la posición de los elementos hijos se define mediante código Kotlin dentro del bloque de contenido.

Gestión del estado en Compose

State en Compose es cualquier valor que puede cambiar con el tiempo. Cuando el estado cambia, Compose programa la recomposición para todos los componentes que leen ese estado. El mecanismo se asemeja a React hooks: mutableStateOf devuelve MutableState<T>, la lectura de .value suscribe automáticamente la composición actual a los cambios.

kotlin
@Composable
fun CounterExample() {
    var count by remember { mutableStateOf(0) }

    Column(modifier = Modifier.padding(16.dp)) {
        Text("Pulsado: $count")
        Button(onClick = { count++ }) {
            Text("Incrementar")
        }
    }
}

@Composable
fun UserScreen(viewModel: UserViewModel) {
    val userName by viewModel.userName.collectAsState()
    Text("Usuario: $userName")
}

remember conserva el valor entre recomposiciones — de lo contrario mutableStateOf se crearía de nuevo en cada actualización de UI. collectAsState() convierte StateFlow de ViewModel en un estado compatible con Compose. Recomendación — usar ViewModel con StateFlow para el estado a nivel de pantalla, y mutableStateOf para el estado local (por ejemplo, tarjeta expandida). Esta separación sigue el principio de componentes inteligentes/mudos.

State Hoisting

State Hoisting es un patrón de elevación del estado desde un componente hijo al padre. El padre pasa el valor y un callback mediante parámetros, el hijo llama al callback al cambiar. El padre mantiene el mutableStateOf, el hijo solo los parámetros. Esto hace que el componente sea reutilizable y testeable: el mismo TextField se puede usar con cualquier fuente de datos.

Modifier — personalización de la apariencia

Modifier es un objeto que describe transformaciones del Composable: tamaño, rellenos, fondo, manejo de clics, animación, desplazamiento. Los modificadores se aplican mediante una cadena de llamadas: Modifier.fillMaxWidth().padding(16.dp).background(Color.Blue).clickable { }. Cada llamada devuelve un nuevo Modifier con la propiedad añadida — sin mutación del objeto original.

El orden de los modificadores es importante. Modifier.padding(16.dp).background(Color.Blue) colorea el área con relleno. Modifier.background(Color.Blue).padding(16.dp) colorea el rectángulo interior, y el relleno permanece transparente. La mecánica se asemeja al modelo de caja CSS: padding primero → background funciona como margin + background; background primero → padding funciona como background + relleno interior. El desarrollador solo necesita recordar: padding primero = margen exterior, padding después = relleno interior.

Modificadores personalizados

Si los modificadores incorporados no son suficientes, se crea uno personalizado mediante Modifier.composed { ... } o Modifier.then(). Dentro de un modificador personalizado se pueden usar mediciones de layout (Modifier.layout { measurable, constraints -> ... }), dibujo (Modifier.drawWithContent { ... }), gestos (Modifier.pointerInput { ... }). Ejemplo: un modificador para animación pulsante al hacer clic — mide el tamaño, al hacer clic inicia una animación de escala mediante animateFloatAsState.

Para animaciones, Compose proporciona animate*AsState (animateFloatAsState, animateColorAsState, animateDpAsState) — los valores se animan entre el estado antiguo y el nuevo al cambiar. Para animaciones de entrada/salida — AnimatedVisibility y AnimatedContent con transiciones integradas (fade, slide, expand). Todas las animaciones funcionan en la capa gráfica sin desencadenar composición innecesaria.

Side Effects: LaunchedEffect, DisposableEffect, remember

Las funciones Composable no deben realizar efectos secundarios directamente (solicitudes de red, temporizadores, suscripciones) — se invocan en cada recomposición, lo que provocaría solicitudes duplicadas. Para efectos secundarios, Compose proporciona una familia de funciones Effect: LaunchedEffect inicia una corrutina al entrar en la composición y la cancela al salir, DisposableEffect — para recursos que requieren limpieza explícita (sensores, BroadcastReceiver).

kotlin
@Composable
fun SensorReader() {
    val context = LocalContext.current
    var sensorValue by remember { mutableStateOf(0f) }

    DisposableEffect(Unit) {
        val sensor = registerSensorListener(context) { value ->
            sensorValue = value
        }
        onDispose {
            unregisterSensorListener(sensor)
        }
    }

    Text("Valor: $sensorValue")
}

@Composable
fun UserGreeting(userId: String) {
    LaunchedEffect(userId) {
        val profile = api.fetchProfile(userId)
        // actualización del estado
    }
}

LaunchedEffect(userId) se reinicia si userId cambia — la corrutina anterior se cancela y se inicia una nueva con el nuevo userId. Esto elimina la gestión manual de cancelación de solicitudes. DisposableEffect(Unit) — un efecto con clave fija Unit, se activa al entrar en la composición y llama a onDispose al salir. SensorReader registra un listener y se da de baja al salir de la pantalla — sin riesgo de fugas.

rememberCoroutineScope

Si es necesario lanzar una corrutina no al entrar en la composición sino ante un evento (clic en un botón), se usa rememberCoroutineScope(). Devuelve un CoroutineScope vinculado al ciclo de vida del Composable, sin necesidad de DisposableEffect. Ejemplo: lanzar una solicitud de red al hacer clic en un botón — scope.launch { viewModel.loadData() }.

Jetpack Compose vs View System: comparación

Elegir entre Compose y View System es la principal cuestión arquitectónica para los desarrolladores Android en 2026. Ambas tecnologías son compatibles con Google, pero Compose es la dirección principal en la que Google invierte recursos. View System recibe solo correcciones críticas y no evoluciona. La diferencia se manifiesta en la sintaxis, la gestión del estado, el rendimiento y el tiempo de desarrollo.

AspectoJetpack ComposeView System
Descripción de UIFunciones Kotlin @ComposableMaquetación XML + Activity/Fragment
EstadomutableStateOf, StateFlow, redibujado automáticofindViewById, manual: setText, notifyDataSetChanged
RendimientoRecomposición inteligente, renderizado CanvasJerarquía de View, measure/layout/draw
Animacionesanimate*AsState, AnimatedVisibility, integradasValueAnimator, ObjectAnimator, Transition
CompatibilidadminSdk 21, puentes ComposeView/AndroidViewTodas las versiones, cualquier
Tamaño APK+3–5 MB para ComposeSin sobrecarga

Para proyectos nuevos, Google recomienda Jetpack Compose como estándar de desarrollo de UI. View System se mantiene para mantener código escrito antes de 2021, y para casos donde el tamaño mínimo del APK es crítico (por ejemplo, para mercados emergentes con dispositivos de gama baja). Compose reduce el volumen de código UI en un 30–50% en comparación con View System gracias a su sintaxis declarativa y animaciones integradas.

Preguntas frecuentes

¿Se puede usar Compose en un proyecto existente con View System?

Sí, mediante ComposeView en la maquetación XML. Añade la dependencia de Compose y envuelve la pantalla o parte de ella en ComposeView { MyComposable() }. La migración es pantalla por pantalla.

¿Por qué mi Composable se redibuja con demasiada frecuencia?

La razón es que el estado se eleva demasiado alto o se utilizan objetos mutables. Solución: derivedStateOf para datos derivados y remember para referencias estables.

¿Cómo implementar una lista en Compose?

Usa LazyColumn (análogo a RecyclerView). Los elementos se crean y reutilizan a medida que se desplaza. Para listas complejas con diferentes tipos de celdas — LazyColumn { items(items, key = { it.id }) { ... } }.

¿Necesito aprender View System antes de Compose?

No, se puede empezar directamente con Compose. El conocimiento de View System ayuda al mantener código heredado, pero Compose es un ecosistema independiente con su propia documentación y patrones.

¿Compose es compatible con Material 3?

Sí, Material 3 es el tema estándar de Compose desde 2023. Se añade mediante implementation("androidx.compose.material3:material3"). Material 2 se considera obsoleto.

Resumen

  • Jetpack Compose — un framework de UI declarativo para Android donde toda la interfaz se escribe en Kotlin mediante funciones @Composable.
  • Recomposition redibuja automáticamente solo los componentes modificados, proporcionando 120 FPS sin optimización manual.
  • State se gestiona mediante mutableStateOf, collectAsState y StateFlow; el patrón State Hoisting hace que los componentes sean reutilizables.
  • Modifier — una cadena de transformaciones para configurar apariencia, animaciones y comportamiento sin herencia de clases.
  • Side Effects (LaunchedEffect, DisposableEffect) aíslan las acciones secundarias de la recomposición, evitando fugas y solicitudes duplicadas.
  • LazyColumn reemplaza a RecyclerView con menos código, y AnimatedVisibility reemplaza cadenas complejas de Animator.
  • Google recomienda Compose para todos los proyectos nuevos; View System se mantiene para código heredado y casos donde el tamaño mínimo del APK es crítico.

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