Produktneuheiten

Neuerungen im Jetpack Compose-Release vom Dezember 2025

Lesezeit: 6 Minuten
Nick Butcher
Product Manager

Die Jetpack Compose-Version vom Dezember 2025 ist jetzt stabil. Sie enthält Version 1.10 der Compose-Kernmodule und Version 1.4 von Material 3 (siehe die vollständige BOM-Zuordnung) und bietet neue Funktionen und erhebliche Leistungsverbesserungen.

Wenn Sie das heutige Release verwenden möchten, aktualisieren Sie die Version Ihrer Compose-BOM auf 2025.12.00:

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

Leistungsverbesserungen

Wir wissen, dass die Laufzeitleistung Ihrer App für Sie und Ihre Nutzer von großer Bedeutung ist. Daher hat das Compose-Team der Leistung höchste Priorität eingeräumt. Diese Version bietet eine Reihe von Verbesserungen, die Sie alle durch ein Upgrade auf die neueste Version erhalten. Unsere internen Scroll-Benchmarks zeigen, dass Compose jetzt die gleiche Leistung wie Views bietet:

janky.png

Benchmark für die Scrollleistung im Vergleich von „Views“ und Jetpack Compose in verschiedenen Versionen von Compose

Pausierbare Komposition im Lazy Prefetch

Die pausierbare Komposition im Lazy Prefetch ist jetzt standardmäßig aktiviert. Dies ist eine grundlegende Änderung der Funktionsweise der Compose-Laufzeitplanung, die darauf ausgelegt ist, Ruckeln bei intensiven UI-Arbeitslasten deutlich zu reduzieren.

Bisher musste eine Komposition, sobald sie gestartet wurde, bis zum Ende ausgeführt werden. Wenn eine Komposition komplex war, konnte dies den Hauptthread länger als ein einzelnes Frame blockieren, was dazu führte, dass die Benutzeroberfläche einfriert. Mit der pausierbaren Komposition kann die Laufzeit ihre Arbeit jetzt „pausieren“, wenn die Zeit knapp wird, und die Arbeit im nächsten Frame fortsetzen. Das ist besonders effektiv, wenn es zusammen mit dem Lazy Layout Prefetch verwendet wird, um Frames im Voraus vorzubereiten. Die in Compose 1.9 eingeführten CacheWindow-APIs für Lazy Layouts sind eine hervorragende Möglichkeit, mehr Inhalte vorab abzurufen und von der pausierbaren Komposition zu profitieren, um eine viel flüssigere UI-Leistung zu erzielen.

pausable.gif

Pausierbare Komposition in Kombination mit Lazy Prefetching kann Ruckeln reduzieren

Wir haben auch die Leistung an anderer Stelle optimiert, mit Verbesserungen bei Modifier.onPlaced, Modifier.onVisibilityChanged und anderen Modifikatorimplementierungen. Wir werden weiterhin daran arbeiten, die Leistung von Compose zu verbessern.

Neue Funktionen

Bindung

Compose bietet eine Reihe von APIs zum Speichern und Verwalten des Status über verschiedene Lebenszyklen hinweg. Mit remember wird der Status beispielsweise über Kompositionen hinweg beibehalten und mit rememberSavable/rememberSerializable über die Neuerstellung von Aktivitäten oder Prozessen hinweg. retain ist eine neue API, die zwischen diesen APIs liegt. Mit ihr können Sie Werte bei Konfigurationsänderungen beibehalten, ohne sie zu serialisieren, aber nicht bei einem Prozessende. Da retain Ihren Status nicht serialisiert, können Sie Objekte wie Lambda-Ausdrücke, Flows und große Objekte wie Bitmaps beibehalten, die nicht einfach serialisiert werden können. Sie können beispielsweise retain verwenden, um einen Media-Player (z. B. ExoPlayer) zu verwalten und dafür zu sorgen, dass die Medienwiedergabe nicht durch eine Konfigurationsänderung unterbrochen wird.

  @Composable

fun MediaPlayer() {

    val applicationContext = LocalContext.current.applicationContext

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

    ...

}

Wir möchten uns bei der AndroidDev-Community (insbesondere beim Circuit-Team) bedanken, die das Design dieser Funktion beeinflusst und dazu beigetragen hat.

Material 1.4

In Version 1.4.0 der material3-Bibliothek wurden einige neue Komponenten und Verbesserungen hinzugefügt:

  • TextField bietet jetzt eine experimentelle TextFieldState-basierte Version, die eine robuster Methode zum Verwalten des Status von Text bietet. Außerdem werden jetzt neue Varianten von SecureTextField und OutlinedSecureTextField angeboten. Die Material-Composable Text unterstützt jetzt das Verhalten „autoSize“.
  • Die Karussellkomponente bietet jetzt eine neue HorizontalCenteredHeroCarousel-Variante.
  • TimePicker unterstützt jetzt das Umschalten zwischen Auswahl- und Eingabemodus.
  • Mit einem vertikalen Ziehpunkt können Nutzer die Größe und/oder Position eines adaptiven Bereichs ändern.
centered-hero-carousel.webp

Horizontal zentriertes Hero-Karussell

Die APIs für Material 3 Expressive werden weiterhin in den Alphaversionen der material3-Bibliothek entwickelt. Weitere Informationen finden Sie in diesem aktuellen Vortrag:

Neue Animationsfunktionen

Wir erweitern unsere Animations-APIs kontinuierlich und bieten jetzt auch Updates für die Anpassung von Animationen für gemeinsame Elemente.

Dynamische gemeinsame Elemente

Standardmäßig wird bei sharedElement()- und sharedBounds()-Animationen versucht,

Das Layout ändert sich, sobald im Zielstatus ein übereinstimmender Schlüssel gefunden wird. Möglicherweise möchten Sie diese Animation jedoch dynamisch deaktivieren, z. B. basierend auf der Navigationsrichtung oder dem aktuellen UI-Status.

Sie können jetzt das an rememberSharedContentState() übergebene SharedContentConfig anpassen, um zu steuern, ob die Übergangsanimation für das gemeinsame Element stattfindet. Mit der Property isEnabled wird festgelegt, ob das gemeinsame Element aktiv ist.

  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

                }

            }

}

Weitere Informationen

Modifier.skipToLookaheadPosition()

In dieser Version wurde der neue Modifier Modifier.skipToLookaheadPosition() hinzugefügt, mit dem die endgültige Position eines Composables bei der Ausführung von Animationen für gemeinsame Elemente beibehalten wird. So lassen sich Übergänge wie Animationen vom Typ „Enthüllen“ realisieren, wie im Androidify-Beispiel mit der progressiven Enthüllung der Kamera zu sehen ist. Weitere Informationen finden Sie in diesem Video: 

Anfangsgeschwindigkeit bei Übergängen mit gemeinsam genutzten Elementen

Mit diesem Release wird eine neue API für Übergänge mit gemeinsam genutzten Elementen, prepareTransitionWithInitialVelocity, eingeführt. Damit können Sie eine Anfangsgeschwindigkeit (z. B. aus einer Geste) an einen Übergang mit gemeinsam genutzten Elementen übergeben:

  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

Übergang für ein gemeinsames Element, der mit einer Anfangsgeschwindigkeit aus einer Geste beginnt

Verschleierte Übergänge

Mit EnterTransition und ExitTransition wird definiert, wie eine zusammensetzbare AnimatedVisibility/AnimatedContent angezeigt oder ausgeblendet wird. Mit einer neuen experimentellen Schleieroption können Sie eine Farbe angeben, mit der Inhalte verdeckt oder verschleiert werden sollen, z.B. durch Ein- oder Ausblenden einer halbtransparenten schwarzen Ebene über den Inhalten:

veil_2.gif

Verschleierte animierte Inhalte – während der Animation ist ein halbtransparentes Tuch (oder eine Gaze) über den Rasterinhalten zu sehen.

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

    ...

}

Anstehende Änderungen

Einstellung von Modifier.onFirstVisible

In Compose 1.9 wurden Modifier.onVisibilityChanged und Modifier.onFirstVisible eingeführt. Nach Prüfung Ihres Feedbacks hat sich herausgestellt, dass der Vertrag von Modifier.onFirstVisible nicht deterministisch eingehalten werden konnte, insbesondere wenn ein Artikel zuerst sichtbar wird. In einem Lazy-Layout können beispielsweise Elemente, die aus dem Darstellungsbereich herausgescrollt werden, verworfen und dann wieder zusammengesetzt werden, wenn sie wieder in den Darstellungsbereich gescrollt werden. In diesem Fall wird der onFirstVisible-Callback noch einmal ausgelöst, da es sich um ein neu zusammengesetztes Element handelt. Ein ähnliches Verhalten tritt auch auf, wenn Sie zu einem zuvor besuchten Bildschirm mit onFirstVisible zurückkehren. Daher haben wir beschlossen, diesen Modifikator im nächsten Compose-Release (1.11) einzustellen und empfehlen, zu onVisibilityChanged zu migrieren. Weitere Informationen finden Sie in der Dokumentation.

Coroutine-Dispatch in Tests

Wir planen, die Coroutine-Dispatching in Tests zu ändern, um die Testanfälligkeit zu verbessern und mehr Probleme zu erkennen. Derzeit wird in Tests die UnconfinedTestDispatcher verwendet, die sich vom Produktionsverhalten unterscheidet. Effekte werden beispielsweise sofort ausgeführt, anstatt in die Warteschlange gestellt zu werden. In einem zukünftigen Release planen wir die Einführung einer neuen API, die standardmäßig StandardTestDispatcher verwendet, um dem Verhalten in der Produktionsumgebung zu entsprechen. Sie können das neue Verhalten jetzt in Version 1.10 ausprobieren:

  @get:Rule // also createAndroidComposeRule, createEmptyComposeRule

val rule = createComposeRule(effectContext = StandardTestDispatcher())

Bei Verwendung von StandardTestDispatcher werden Aufgaben in die Warteschlange gestellt. Daher müssen Sie Synchronisierungsmechanismen wie composeTestRule.waitForIdle() oder composeTestRule.runOnIdle() verwenden. Wenn in Ihrem Test runTest verwendet wird, müssen Sie dafür sorgen, dass runTest und Ihre Compose-Regel dieselbe StandardTestDispatcher-Instanz für die Synchronisierung verwenden.

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

}

Tools

Tolle APIs verdienen tolle Tools. Deshalb gibt es in Android Studio einige Neuerungen für Compose-Entwickler:

In dieser aktuellen Demonstration können Sie sich ansehen, wie diese Tools funktionieren:

Viel Spaß beim Erstellen

Wir investieren weiterhin in Jetpack Compose, um Ihnen die APIs und Tools zur Verfügung zu stellen, die Sie zum Erstellen ansprechender, umfangreicher UIs benötigen. Wir freuen uns über Ihr Feedback zu diesen Änderungen und darüber, was Sie als Nächstes in unserem Issue Tracker sehen möchten.

Verfasst von:

Weiterlesen