Notizie sui prodotti

Novità della release di dicembre 2025 di Jetpack Compose

Lettura di 6 minuti
Nick Butcher
Product Manager

Oggi, la release di dicembre 2025 di Jetpack Compose è stabile. Contiene la versione 1.10 dei moduli Compose di base e la versione 1.4 di Material 3 (vedi la mappatura completa della distinta base), aggiungendo nuove funzionalità e importanti miglioramenti delle prestazioni.

Per utilizzare la release di oggi, esegui l'upgrade della versione della distinta base di Compose a 2025.12.00:

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

Miglioramenti delle prestazioni

Sappiamo che le prestazioni di runtime della tua app sono estremamente importanti per te e per i tuoi utenti, quindi le prestazioni sono state una priorità assoluta per il team di Compose. Questa release introduce una serie di miglioramenti, che puoi ottenere tutti semplicemente eseguendo l'upgrade all'ultima versione. I nostri benchmark di scorrimento interni mostrano che Compose ora corrisponde alle prestazioni che vedresti se utilizzassi le visualizzazioni:

janky.png

Benchmark delle prestazioni di scorrimento che confronta le visualizzazioni e Jetpack Compose in diverse versioni di Compose

Composizione in pausa nel prefetch lazy

La composizione in pausa nel prefetch lazy è ora attivata per impostazione predefinita. Si tratta di una modifica fondamentale al funzionamento della pianificazione di runtime di Compose, progettata per ridurre significativamente il jank durante i carichi di lavoro UI pesanti.

In precedenza, una volta avviata una composizione, doveva essere eseguita fino al completamento. Se una composizione era complessa, poteva bloccare il thread principale per un periodo di tempo superiore a un singolo frame, causando il blocco dell'UI. Con la composizione in pausa, il runtime può ora "mettere in pausa" il suo lavoro se sta per scadere il tempo e riprenderlo nel frame successivo. Questo è particolarmente efficace se utilizzato con il prefetch del layout lazy per preparare i frame in anticipo. Le API CacheWindow del layout lazy introdotte in Compose 1.9 sono un ottimo modo per precaricare più contenuti e sfruttare la composizione in pausa per ottenere prestazioni dell'UI molto più fluide.

pausable.gif

La composizione in pausa combinata con il prefetch lazy aiuta a ridurre il jank

Abbiamo anche ottimizzato le prestazioni altrove, con miglioramenti a Modifier.onPlaced, Modifier.onVisibilityChanged e altre implementazioni di modificatori. Continueremo a investire nel miglioramento delle prestazioni di Compose.

Nuove funzionalità

Fidelizza

Compose offre una serie di API per conservare e gestire lo stato in diversi cicli di vita; ad esempio, remember mantiene lo stato tra le composizioni e rememberSavable/rememberSerializable per mantenerlo durante la ricreazione dell'attività o del processo.retain è una nuova API che si trova tra queste API e ti consente di mantenere i valori durante le modifiche alla configurazione senza essere serializzati, ma non durante l'interruzione del processo. Poiché retain non serializza lo stato, puoi mantenere oggetti come espressioni lambda, flussi e oggetti di grandi dimensioni come bitmap, che non possono essere serializzati facilmente. Ad esempio, puoi utilizzare retain per gestire un player multimediale (ad esempio ExoPlayer) per assicurarti che la riproduzione dei contenuti multimediali non venga interrotta da una modifica alla configurazione.

  @Composable

fun MediaPlayer() {

    val applicationContext = LocalContext.current.applicationContext

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

    ...

}

Ringraziamo la community AndroidDev (in particolare il team di Circuit), che ha influenzato e contribuito alla progettazione di questa funzionalità.

Material 1.4

La versione 1.4.0 della libreria material3 aggiunge una serie di nuovi componenti e miglioramenti:

centered-hero-carousel.webp

Carosello orizzontale con elemento principale centrato

Tieni presente che le API Material 3 Expressive continuano a essere sviluppate nelle release alpha della libreria material3. Per saperne di più, guarda questo recente intervento:

Nuove funzionalità di animazione

Continuiamo a espandere le nostre API di animazione, inclusi gli aggiornamenti per la personalizzazione delle animazioni degli elementi condivisi.

Elementi condivisi dinamici

Per impostazione predefinita, le animazioni sharedElement() e sharedBounds() tentano di animare

le modifiche al layout ogni volta che viene trovata una chiave corrispondente nello stato di destinazione. Tuttavia, potresti voler disattivare questa animazione in modo dinamico in base a determinate condizioni, come la direzione di navigazione o lo stato attuale dell'UI.

Per controllare se la transizione dell'elemento condiviso si verifica, ora puoi personalizzare SharedContentConfig passato a rememberSharedContentState(). La proprietà isEnabled determina se l'elemento condiviso è attivo.

  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

                }

            }

}

Per saperne di più, consulta la documentazione.

Modifier.skipToLookaheadPosition()

In questa release è stato aggiunto un nuovo modificatore, Modifier.skipToLookaheadPosition(), che mantiene la posizione finale di un composable durante l'esecuzione delle animazioni degli elementi condivisi. Ciò consente di eseguire transizioni come l'animazione di tipo "rivela", come si può vedere nell'esempio di Androidify con la rivelazione progressiva della fotocamera. Per saperne di più, guarda il suggerimento video qui: 

Velocità iniziale nelle transizioni degli elementi condivisi

Questa release aggiunge una nuova API di transizione degli elementi condivisi, prepareTransitionWithInitialVelocity, che consente di passare una velocità iniziale (ad es. da un gesto) a una transizione degli elementi condivisi:

  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 transizione degli elementi condivisi che inizia con una velocità iniziale da un gesto

Transizioni velate

EnterTransitionExitTransition definiscono come un AnimatedVisibility/AnimatedContent composable viene visualizzato o scompare. Una nuova opzione di velatura sperimentale consente di specificare un colore per velare o oscurare i contenuti; ad esempio, dissolvendo un livello nero semi-opaco sui contenuti:

veil_2.gif

Contenuti animati velati: nota la velatura (o oscuramento) semi-opaca sui contenuti della griglia durante l'animazione

  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 ->

    ...

}

Modifiche imminenti

Deprecazione di Modifier.onFirstVisible

Compose 1.9 ha introdotto Modifier.onVisibilityChangedModifier.onFirstVisible. Dopo aver esaminato il tuo feedback, è diventato evidente che il contratto di Modifier.onFirstVisible non era possibile rispettare in modo deterministico; in particolare, quando un elemento diventa per la prima volta visibile. Ad esempio, un layout lazy può eliminare gli elementi che scorrono fuori dalla finestra e poi comporli di nuovo se scorrono di nuovo nella visualizzazione. In questa circostanza, il callback onFirstVisible verrà attivato di nuovo, poiché si tratta di un elemento appena composto. Un comportamento simile si verificherebbe anche quando si torna a una schermata visitata in precedenza contenente onFirstVisible. Pertanto, abbiamo deciso di ritirare questo modificatore nella prossima release di Compose (1.11) e consigliamo di eseguire la migrazione a onVisibilityChanged. Per saperne di più, consulta la documentazione.

Invio di coroutine nei test

Prevediamo di modificare l'invio di coroutine nei test per migliorare l'instabilità dei test e rilevare più problemi. Attualmente, i test utilizzano UnconfinedTestDispatcher, che differisce dal comportamento di produzione; ad esempio, gli effetti potrebbero essere eseguiti immediatamente anziché essere messi in coda. In una release futura, prevediamo di introdurre una nuova API che utilizza StandardTestDispatcher per impostazione predefinita per corrispondere ai comportamenti di produzione. Puoi provare il nuovo comportamento ora nella versione 1.10:

  @get:Rule // also createAndroidComposeRule, createEmptyComposeRule

val rule = createComposeRule(effectContext = StandardTestDispatcher())

L'utilizzo di StandardTestDispatcher metterà in coda le attività, quindi devi utilizzare meccanismi di sincronizzazione come composeTestRule.waitForIdle() o composeTestRule.runOnIdle(). Se il test utilizza runTest, devi assicurarti che runTest e la regola di Compose condividano la stessa istanza StandardTestDispatcher per la sincronizzazione.

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

}

Strumenti

Le API di qualità meritano strumenti di qualità e Android Studio ha una serie di aggiunte recenti per gli sviluppatori di Compose:

Per vedere questi strumenti in azione, guarda questa recente dimostrazione:

Buon lavoro con Compose

Continuiamo a investire in Jetpack Compose per fornirti le API e gli strumenti di cui hai bisogno per creare UI ricche e accattivanti. Il tuo contributo è importante per noi, quindi condividi il tuo feedback su queste modifiche o su ciò che vorresti vedere in futuro nel nostro strumento di monitoraggio dei problemi.

Continua a leggere