Notícias sobre produtos

Novidades da versão de dezembro de 2025 do Jetpack Compose

Leitura de 6 minutos
Nick Butcher
Gerente de produtos

Hoje, o lançamento de dezembro de 2025 do Jetpack Compose está estável. Ela contém a versão 1.10 dos módulos principais do Compose e a versão 1.4 do Material 3. Consulte o mapeamento completo da BOM (link em inglês), que adiciona novos recursos e melhorias significativas de performance.

Para usar a versão de hoje, faça upgrade da versão da BOM do Compose para 2025.12.00:

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

Melhorias de desempenho

Sabemos que o desempenho de execução do seu app é muito importante para você e seus usuários. Por isso, o desempenho tem sido uma das principais prioridades da equipe do Compose. Esta versão traz várias melhorias, e você pode aproveitar todas elas apenas atualizando para a versão mais recente. Nossos comparativos internos de rolagem mostram que o Compose agora corresponde à performance que você teria ao usar Views:

janky.png

Comparativo de desempenho de rolagem entre Views e Jetpack Compose em diferentes versões do Compose

Composição pausável na pré-busca lenta

A composição pausável na pré-busca lenta agora está ativada por padrão. Essa é uma mudança fundamental na forma como os agendamentos de tempo de execução do Compose funcionam, projetada para reduzir significativamente o jank durante cargas de trabalho pesadas da interface.

Antes, uma composição precisava ser executada até a conclusão. Se uma composição fosse complexa, isso poderia bloquear a linha de execução principal por mais tempo do que um único frame, fazendo com que a interface congelasse. Com a composição pausável, o tempo de execução agora pode "pausar" o trabalho se estiver acabando o tempo e retomar no próximo frame. Isso é particularmente eficaz quando usado com a pré-busca de layout lento para preparar frames com antecedência. As APIs CacheWindow do layout lento introduzidas no Compose 1.9 são uma ótima maneira de pré-buscar mais conteúdo e aproveitar a composição pausável para produzir um desempenho de UI muito mais suave.

pausable.gif

A composição pausável combinada com a pré-busca lenta ajuda a reduzir o jank

Também otimizamos o desempenho em outros lugares, com melhorias em Modifier.onPlaced, Modifier.onVisibilityChanged e outras implementações de modificadores. Vamos continuar investindo na melhoria da performance do Compose.

Novos recursos

Reter

O Compose oferece várias APIs para manter e gerenciar o estado em diferentes ciclos de vida. Por exemplo, remember mantém o estado em várias composições, e rememberSavable/rememberSerializable mantém o estado em várias recriações de atividades ou processos. retain é uma nova API que fica entre essas APIs, permitindo manter valores em todas as mudanças de configuração sem serem serializados, mas não em caso de encerramento do processo. Como o retain não serializa seu estado, é possível manter objetos como expressões lambda, fluxos e objetos grandes, como bitmaps, que não podem ser facilmente serializados. Por exemplo, você pode usar retain para gerenciar um player de mídia (como o ExoPlayer) e garantir que a reprodução de mídia não seja interrompida por uma mudança de configuração.

@Composable

fun MediaPlayer() {

    val applicationContext = LocalContext.current.applicationContext

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

    ...

}

Agradecemos à comunidade AndroidDev, especialmente à equipe do Circuit, que influenciou e contribuiu para o design desse recurso.

Material 1.4

A versão 1.4.0 da biblioteca material3 adiciona vários novos componentes e melhorias:

centered-hero-carousel.webp

Carrossel de destaque centralizado horizontal

As APIs Material 3 Expressive continuam sendo desenvolvidas nas versões Alfa da biblioteca material3. Para saber mais, assista esta palestra recente:

Novos recursos de animação

Continuamos expandindo nossas APIs de animação, incluindo atualizações para personalizar animações de elementos compartilhados.

Elementos compartilhados dinâmicos

Por padrão, as animações sharedElement() e sharedBounds() tentam animar

O layout muda sempre que uma chave correspondente é encontrada no estado de destino. No entanto, talvez você queira desativar essa animação dinamicamente com base em determinadas condições, como a direção da navegação ou o estado atual da interface.

Para controlar se a transição de elemento compartilhado ocorre, agora é possível personalizar o SharedContentConfig transmitido para rememberSharedContentState(). A propriedade isEnabled determina se o elemento compartilhado está ativo.

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

                }

            }

}

Consulte a documentação para saber mais.

Modifier.skipToLookaheadPosition()

Um novo modificador, Modifier.skipToLookaheadPosition(), foi adicionado nesta versão, que mantém a posição final de um elemento combinável ao realizar animações de elementos compartilhados. Isso permite realizar transições como animação do tipo "revelar", como pode ser visto na amostra do Androidify com a revelação progressiva da câmera. Confira a dica de vídeo aqui para mais informações: 

Velocidade inicial em transições de elementos compartilhados

Esta versão adiciona uma nova API de transição de elemento compartilhado, prepareTransitionWithInitialVelocity, que permite transmitir uma velocidade inicial (por exemplo, de um gesto) a uma transição de elemento compartilhado:

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

Uma transição de elemento compartilhado que começa com uma velocidade inicial de um gesto

Transições sutis

EnterTransition e ExitTransition definem como um elemento combinável AnimatedVisibility/AnimatedContent aparece ou desaparece. Uma nova opção experimental de véu permite especificar uma cor para velar ou encobrir o conteúdo. Por exemplo, aparecendo/desaparecendo uma camada preta semitransparente sobre o conteúdo:

veil_2.gif

Conteúdo animado encoberto: observe o véu (ou tela) semitransparente sobre o conteúdo da grade durante a animação

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óximas mudanças

Suspensão de uso de Modifier.onFirstVisible

O Compose 1.9 introduziu Modifier.onVisibilityChanged e Modifier.onFirstVisible. Depois de analisar seu feedback, ficou evidente que não é possível honrar o contrato de Modifier.onFirstVisible de forma determinística, principalmente quando um item primeiro fica visível. Por exemplo, um layout Lazy pode descartar itens que rolam para fora da janela de visualização e depois compô-los novamente se eles rolarem de volta para a visualização. Nesse caso, o callback onFirstVisible seria acionado novamente, já que é um item recém-composto. Um comportamento semelhante também ocorreria ao navegar de volta para uma tela visitada anteriormente que continha onFirstVisible. Por isso, decidimos descontinuar esse modificador na próxima versão do Compose (1.11) e recomendamos migrar para onVisibilityChanged. Consulte a documentação para mais informações.

Envio de corrotinas em testes

Planejamos mudar a distribuição de corrotinas em testes para melhorar a instabilidade e detectar mais problemas. No momento, os testes usam o UnconfinedTestDispatcher, que é diferente do comportamento de produção. Por exemplo, os efeitos podem ser executados imediatamente em vez de serem enfileirados. Em uma versão futura, planejamos lançar uma nova API que usa StandardTestDispatcher por padrão para corresponder aos comportamentos de produção. Teste o novo comportamento agora na versão 1.10:

@get:Rule // also createAndroidComposeRule, createEmptyComposeRule

val rule = createComposeRule(effectContext = StandardTestDispatcher())

O uso de StandardTestDispatcher vai enfileirar tarefas. Portanto, use mecanismos de sincronização como composeTestRule.waitForIdle() ou composeTestRule.runOnIdle(). Se o teste usar runTest, verifique se runTest e sua regra do Compose compartilham a mesma instância StandardTestDispatcher para sincronização.

// 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 { /* ... */ }

}

Ferramentas

APIs excelentes merecem ferramentas excelentes, e o Android Studio tem várias adições recentes para desenvolvedores do Compose:

Para ver essas ferramentas em ação, assista esta demonstração recente:

Divirta-se!

Continuamos investindo no Jetpack Compose para oferecer as APIs e ferramentas necessárias para criar IUs bonitas e avançadas. Sua opinião é muito importante. Compartilhe seu feedback sobre essas mudanças ou o que você gostaria de ver em seguida no nosso rastreador de problemas.

Escrito por:

Continuar lendo