Novedades de productos

Novedades de la versión de diciembre de 2025 de Jetpack Compose

Lectura de 6 min
Nick Butcher
Gerente de producto

Hoy, la versión de diciembre de 2025 de Jetpack Compose es estable. Contiene la versión 1.10 de los módulos principales de Compose y la versión 1.4 de Material 3 (consulta la asignación completa de la BOM), lo que agrega nuevas funciones y mejoras importantes en el rendimiento.

Para usar la versión de hoy, actualiza tu versión de la BOM de Compose a 2025.12.00:

implementation(platform("androidx.compose:compose-bom:2025.12.00"))

Mejoras en el rendimiento

Sabemos que el rendimiento en el tiempo de ejecución de tu app es muy importante para ti y tus usuarios, por lo que el rendimiento ha sido una prioridad importante para el equipo de Compose. Esta versión incluye varias mejoras, y puedes obtenerlas todas con solo actualizar a la versión más reciente. Nuestros parámetros de referencia de desplazamiento internos muestran que Compose ahora coincide con el rendimiento que verías si usaras Views:

janky.png

Parámetro de referencia de rendimiento de desplazamiento que compara Views y Jetpack Compose en diferentes versiones de Compose

Composición pausada en la recuperación previa diferida

La composición pausada en la recuperación previa diferida ahora está habilitada de forma predeterminada. Este es un cambio fundamental en la forma en que funciona la programación del tiempo de ejecución de Compose, diseñado para reducir significativamente el bloqueo durante las cargas de trabajo pesadas de la IU.

Anteriormente, una vez que comenzaba una composición, debía ejecutarse hasta completarse. Si una composición era compleja, podía bloquear el subproceso principal durante más de un fotograma, lo que provocaba que la IU se congelara. Con la composición pausada, el tiempo de ejecución ahora puede "pausar" su trabajo si se queda sin tiempo y reanudarlo en el siguiente fotograma. Esto es particularmente eficaz cuando se usa con la recuperación previa de diseño diferido para preparar fotogramas con anticipación. Las APIs de Lazy layout CacheWindow que se introdujeron en Compose 1.9 son una excelente manera de recuperar previamente más contenido y beneficiarse de la composición pausada para producir un rendimiento de la IU mucho más fluido.

pausable.gif

La composición pausada combinada con la recuperación previa diferida ayuda a reducir el bloqueo

También optimizamos el rendimiento en otros lugares, con mejoras en Modifier.onPlaced, Modifier.onVisibilityChanged y otras implementaciones de modificadores. Seguiremos invirtiendo en mejorar el rendimiento de Compose.

Nuevas funciones

Retain

Compose ofrece varias APIs para mantener y administrar el estado en diferentes ciclos de vida. Por ejemplo, remember conserva el estado en las composiciones y rememberSavable/rememberSerializable para conservarlo en la actividad o la recreación del proceso.retain es una API nueva que se encuentra entre estas APIs, lo que te permite conservar valores en los cambios de configuración sin serializar, pero no en el cierre del proceso. Como retain no serializa tu estado, puedes conservar objetos como expresiones lambda, flujos y objetos grandes como mapas de bits, que no se pueden serializar fácilmente. Por ejemplo, puedes usar retain para administrar un reproductor multimedia (como ExoPlayer) para asegurarte de que la reproducción de contenido multimedia no se interrumpa por un cambio de configuración.

@Composable

fun MediaPlayer() {

    val applicationContext = LocalContext.current.applicationContext

    val exoPlayer = retain { ExoPlayer.Builder(applicationContext).apply { ... }.build() }

    ...

}

Queremos agradecer a la comunidad de AndroidDev (en especial, al equipo de Circuit), que influyó y contribuyó al diseño de esta función.

Material 1.4

La versión 1.4.0 de la biblioteca material3 agrega varios componentes nuevos y mejoras:

centered-hero-carousel.webp

Carrusel de héroes centrado horizontalmente

Ten en cuenta que las APIs de Material 3 Expressive se siguen desarrollando en las versiones alfa de la material3 biblioteca. Para obtener más información, mira esta charla reciente:

Nuevas funciones de animación

Seguimos expandiendo nuestras APIs de animación, incluidas las actualizaciones para personalizar las animaciones de elementos compartidos.

Elementos compartidos dinámicos

De forma predeterminada, las animaciones sharedElement() y sharedBounds() intentan animar

cambios de diseño cada vez que se encuentra una clave coincidente en el estado objetivo. Sin embargo, es posible que desees desactivar esta animación de forma dinámica según ciertas condiciones, como la dirección de navegación o el estado actual de la IU.

Para controlar si se produce la transición de elementos compartidos, ahora puedes personalizar el SharedContentConfig que se pasa a rememberSharedContentState(). La propiedad isEnabled determina si el elemento compartido está activo.

SharedTransitionLayout {

        val transition = updateTransition(currentState)

        transition.AnimatedContent { targetState ->

            // Create the configuration that depends on state changing.

            fun animationConfig() : SharedTransitionScope.SharedContentConfig {

                return object : SharedTransitionScope.SharedContentConfig {

                    override val SharedTransitionScope.SharedContentState.isEnabled: Boolean

                        get() =

                            // determine whether to perform a shared element transition

                }

            }

}

Consulta la documentación para obtener más información.

Modifier.skipToLookaheadPosition()

En esta versión, se agregó un nuevo modificador, Modifier.skipToLookaheadPosition(), que mantiene la posición final de un elemento componible cuando se realizan animaciones de elementos compartidos. Esto permite realizar transiciones como la animación de tipo "revelar", como se puede ver en la muestra de Androidify con la revelación progresiva de la cámara. Consulta la sugerencia de video aquí para obtener más información: 

Velocidad inicial en transiciones de elementos compartidos

Esta versión agrega una nueva API de transición de elementos compartidos, prepareTransitionWithInitialVelocity, que te permite pasar una velocidad inicial (p.ej., desde un gesto) a una transición de elementos compartidos:

Modifier.fillMaxSize()

    .draggable2D(

        rememberDraggable2DState { offset += it },

        onDragStopped = { velocity ->

            // Set up the initial velocity for the upcoming shared element

            // transition.

            sharedContentStateForDraggableCat

                ?.prepareTransitionWithInitialVelocity(velocity)

            showDetails = false

        },

    )
fling-shared.gif

Una transición de elementos compartidos que comienza con una velocidad inicial desde un gesto

Transiciones veladas

EnterTransitionExitTransition definen cómo aparece o desaparece un elemento componible AnimatedVisibility/AnimatedContent. Una nueva opción de velo experimental te permite especificar un color para velar o cubrir contenido, p.ej., atenuar o atenuar una capa negra semitransparente sobre el contenido:

veil_2.gif

Contenido animado velado: observa el velo (o la cortina) semitransparente sobre el contenido de la cuadrícula durante la animación

AnimatedContent(

    targetState = page,

    modifier = Modifier.fillMaxSize().weight(1f),

    transitionSpec = {

        if (targetState > initialState) {

            (slideInHorizontally { it } togetherWith

                    slideOutHorizontally { -it / 2 } + veilOut(targetColor = veilColor))

        } else {

            slideInHorizontally { -it / 2 } +

                    unveilIn(initialColor = veilColor) togetherWith slideOutHorizontally { it }

        }

    },

) { targetPage ->

    ...

}

Próximos cambios

Obsolecencia de Modifier.onFirstVisible

Compose 1.9 introdujo Modifier.onVisibilityChangedModifier.onFirstVisible. Después de revisar tus comentarios, se hizo evidente que el contrato de Modifier.onFirstVisible no se podía cumplir de forma determinista, específicamente, cuando un elemento se hace visible por primera vez. Por ejemplo, un diseño diferido puede descartar elementos que se desplazan fuera de la ventana gráfica y, luego, volver a componerlos si vuelven a la vista. En esta circunstancia, la devolución de llamada onFirstVisible se activaría de nuevo, ya que es un elemento recién compuesto. También se produciría un comportamiento similar cuando se navega de regreso a una pantalla visitada anteriormente que contiene onFirstVisible. Por lo tanto, decidimos declarar obsoleto este modificador en la próxima versión de Compose (1.11) y recomendamos migrar a onVisibilityChanged. Consulta la documentación para obtener más información.

Despacho de corrutinas en pruebas

Planeamos cambiar el despacho de corrutinas en las pruebas para mejorar la inestabilidad de las pruebas y detectar más problemas. Actualmente, las pruebas usan UnconfinedTestDispatcher, que difiere del comportamiento de producción. Por ejemplo, los efectos pueden ejecutarse de inmediato en lugar de ponerse en cola. En una versión futura, planeamos introducir una nueva API que use StandardTestDispatcher de forma predeterminada para que coincida con los comportamientos de producción. Puedes probar el nuevo comportamiento ahora en 1.10:

@get:Rule // also createAndroidComposeRule, createEmptyComposeRule

val rule = createComposeRule(effectContext = StandardTestDispatcher())

El uso de StandardTestDispatcher pondrá en cola las tareas, por lo que debes usar mecanismos de sincronización como composeTestRule.waitForIdle() o composeTestRule.runOnIdle(). Si tu prueba usa runTest, debes asegurarte de que runTest y tu regla de Compose compartan la misma instancia StandardTestDispatcher para la sincronización.

// 1. Create a SINGLE dispatcher instance

val testDispatcher = StandardTestDispatcher()



// 2. Pass it to your Compose rule

@get:Rule

val composeRule = createComposeRule(effectContext = testDispatcher)



@Test

// 3. Pass the *SAME INSTANCE* to runTest

fun myTest() = runTest(testDispatcher) {

    composeRule.setContent { /* ... */ }

}

Herramientas

Las excelentes APIs merecen excelentes herramientas, y Android Studio tiene varias incorporaciones recientes para desarrolladores de Compose:

Para ver estas herramientas en acción, mira esta demostración reciente:

Feliz composición

Seguimos invirtiendo en Jetpack Compose para proporcionarte las APIs y las herramientas que necesitas para crear IU atractivas y enriquecidas. Valoramos tus comentarios, así que comparte tus opiniones sobre estos cambios o lo que te gustaría ver a continuación en nuestro registro de errores.

Escrito por:

Seguir leyendo