Wiadomości o usługach

Nowości w Jetpack Compose w grudniu 2025 r.

Czas czytania: 6 minut
Nick Butcher
Menedżer produktu

Wersja Jetpack Compose z grudnia 2025 r. jest już stabilna. Zawiera wersję 1.10 podstawowych modułów Compose i wersję 1.4 biblioteki Material 3 (pełne mapowanie BOM), które dodają nowe funkcje i znacznie poprawiają wydajność.

Aby korzystać z dzisiejszej wersji, uaktualnij wersję BOM Compose do 2025.12.00:

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

Ulepszenia wydajności

Wiemy, że wydajność aplikacji jest niezwykle ważna dla Ciebie i Twoich użytkowników, dlatego zespół Compose przykłada do niej dużą wagę. Ta wersja zawiera wiele ulepszeń, które uzyskasz, aktualizując ją do najnowszej wersji. Nasze wewnętrzne testy przewijania pokazują, że Compose osiąga teraz skuteczność porównywalną z tą, którą można uzyskać przy użyciu widoków:

janky.png

Porównanie wydajności przewijania w przypadku widoków i Jetpack Compose w różnych wersjach Compose

Możliwość wstrzymania kompozycji w przypadku leniwego pobierania z wyprzedzeniem

Kompozycja z możliwością wstrzymania w przypadku wstępnego wczytywania z opóźnieniem jest teraz domyślnie włączona. Jest to zasadnicza zmiana w sposobie działania harmonogramów środowiska wykonawczego Compose, która ma na celu znaczne zmniejszenie zacinania się podczas intensywnych zadań interfejsu.

Wcześniej po rozpoczęciu kompozycji musiała ona zostać ukończona. Jeśli kompozycja była złożona, mogło to blokować wątek główny przez dłużej niż jedną klatkę, co powodowało zawieszanie się interfejsu. Dzięki kompozycji z możliwością wstrzymania środowisko wykonawcze może teraz „wstrzymać” pracę, jeśli kończy mu się czas, i wznowić ją w następnej klatce. Jest to szczególnie skuteczne w połączeniu z wstępnym pobieraniem układu z opóźnionym ładowaniem, które przygotowuje ramki z wyprzedzeniem. Interfejsy API CacheWindow w układzie Lazy wprowadzone w Compose 1.9 to świetny sposób na wstępne pobieranie większej ilości treści i korzystanie z kompozycji z możliwością wstrzymania, co zapewnia znacznie płynniejsze działanie interfejsu.

pausable.gif

Kompozycja z możliwością wstrzymania w połączeniu z leniwym pobieraniem wstępnym pomaga ograniczyć zacinanie się

Zoptymalizowaliśmy też działanie innych funkcji, w tym Modifier.onPlacedModifier.onVisibilityChanged oraz innych implementacji modyfikatorów. Będziemy nadal inwestować w poprawę wydajności Compose.

Nowe funkcje

Zachowaj

Compose udostępnia kilka interfejsów API do przechowywania stanu i zarządzania nim w różnych cyklach życia. Na przykład remember utrzymuje stan w różnych kompozycjach, a rememberSavable/rememberSerializable – w różnych aktywnościach lub procesach. retain to nowy interfejs API, który znajduje się między tymi interfejsami API i umożliwia zachowywanie wartości przy zmianach konfiguracji bez serializacji, ale nie przy śmierci procesu. retain nie serializuje stanu, więc możesz zachowywać obiekty takie jak wyrażenia lambda, przepływy i duże obiekty, np. mapy bitowe, których nie można łatwo serializować. Możesz na przykład użyć retain do zarządzania odtwarzaczem multimediów (np. ExoPlayer), aby mieć pewność, że odtwarzanie multimediów nie zostanie przerwane przez zmianę konfiguracji.

@Composable

fun MediaPlayer() {

    val applicationContext = LocalContext.current.applicationContext

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

    ...

}

Chcemy podziękować społeczności AndroidDev (zwłaszcza zespołowi Circuit), która miała wpływ na projekt tej funkcji i przyczyniła się do jej powstania.

Material 1.4

Wersja 1.4.0 biblioteki material3 zawiera szereg nowych komponentów i ulepszeń:

centered-hero-carousel.webp

Poziomy karuzela powitalna wyśrodkowana

Pamiętaj, że interfejsy API Material 3 Expressive są nadal rozwijane w wersjach alfa biblioteki material3. Więcej informacji znajdziesz w tym nagraniu:

Nowe funkcje animacji

Stale rozwijamy nasze interfejsy API animacji, w tym aktualizacje umożliwiające dostosowywanie animacji wspólnych elementów.

Dynamiczne elementy wspólne

Domyślnie animacje sharedElement()sharedBounds() próbują animować

układ zmienia się za każdym razem, gdy w stanie docelowym zostanie znaleziony pasujący klucz. Możesz jednak dynamicznie wyłączać tę animację w zależności od określonych warunków, np. kierunku nawigacji lub bieżącego stanu interfejsu.

Aby określić, czy ma nastąpić przejście elementu współdzielonego, możesz teraz dostosować wartość SharedContentConfig przekazywaną do funkcji rememberSharedContentState(). Właściwość isEnabled określa, czy udostępniony element jest aktywny.

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

                }

            }

}

Więcej informacji znajdziesz w dokumentacji.

Modifier.skipToLookaheadPosition()

W tej wersji dodaliśmy nowy modyfikator Modifier.skipToLookaheadPosition(), który zachowuje ostateczną pozycję elementu kompozycyjnego podczas wykonywania animacji elementów udostępnionych. Umożliwia to wykonywanie przejść, takich jak animacja typu „reveal”, co widać w przykładzie Androidify z progresywnym ujawnianiem kamery. Więcej informacji znajdziesz w tym filmie: 

Prędkość początkowa w przypadku przejść między elementami współdzielonymi

Ta wersja zawiera nowy interfejs API przejścia elementu udostępnionego, prepareTransitionWithInitialVelocity, który umożliwia przekazywanie początkowej prędkości (np. z gestu) do przejścia elementu udostępnionego:

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

Przejście elementu współdzielonego, które rozpoczyna się od początkowej prędkości uzyskanej za pomocą gestu

Przejścia zasłonięte

EnterTransitionExitTransition określają, jak element kompozycyjny AnimatedVisibility/AnimatedContent pojawia się lub znika. Nowa eksperymentalna opcja zasłony umożliwia określenie koloru zasłony lub ekranu treści, np. stopniowe pojawianie się i znikanie półprzezroczystej czarnej warstwy na treści:

veil_2.gif

Treści animowane z zasłoną – zwróć uwagę na półprzezroczystą zasłonę (lub siatkę) na treściach siatki podczas animacji

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

    ...

}

Nadchodzące zmiany

Wycofanie funkcji Modifier.onFirstVisible

W Compose 1.9 wprowadzono Modifier.onVisibilityChangedModifier.onFirstVisible. Po zapoznaniu się z Twoją opinią okazało się, że nie można było w sposób deterministyczny dotrzymać warunków umowy dotyczących Modifier.onFirstVisible, zwłaszcza gdy element po raz pierwszy staje się widoczny. Na przykład układ Lazy może usuwać elementy, które znikają z obszaru widocznego na ekranie, a następnie ponownie je tworzyć, gdy wracają do widoku. W takiej sytuacji wywołanie zwrotne onFirstVisible zostanie uruchomione ponownie, ponieważ jest to nowo utworzony element. Podobne zachowanie wystąpi również podczas powrotu do wcześniej odwiedzonego ekranu zawierającego onFirstVisible. Dlatego zdecydowaliśmy się wycofać ten modyfikator w następnej wersji Compose (1.11) i zalecamy przejście na onVisibilityChanged. Więcej informacji znajdziesz w dokumentacji.

Wysyłanie coroutine w testach

Planujemy zmienić wysyłanie współprogramów w testach, aby zmniejszyć ich niestabilność i wykrywać więcej problemów. Obecnie testy korzystają z UnconfinedTestDispatcher, co różni się od działania w środowisku produkcyjnym. Na przykład efekty mogą być uruchamiane natychmiast, a nie dodawane do kolejki. W przyszłej wersji planujemy wprowadzić nowy interfejs API, który domyślnie będzie używać StandardTestDispatcher, aby dopasować się do zachowań w środowisku produkcyjnym. Nowe działanie możesz wypróbować już teraz w wersji 1.10:

@get:Rule // also createAndroidComposeRule, createEmptyComposeRule

val rule = createComposeRule(effectContext = StandardTestDispatcher())

Użycie StandardTestDispatcher spowoduje umieszczenie zadań w kolejce, dlatego musisz użyć mechanizmów synchronizacji, takich jak composeTestRule.waitForIdle() lub composeTestRule.runOnIdle(). Jeśli test korzysta z runTest, musisz zadbać o to, aby runTest i reguła tworzenia wiadomości korzystały z tej samej instancji StandardTestDispatcher na potrzeby synchronizacji.

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

}

Narzędzia

Świetne interfejsy API zasługują na świetne narzędzia, a Android Studio ma kilka nowości dla deweloperów korzystających z Compose:

Aby zobaczyć te narzędzia w akcji, obejrzyj tę demonstrację:

Przyjemnego pisania

Stale inwestujemy w Jetpack Compose, aby udostępniać Ci interfejsy API i narzędzia potrzebne do tworzenia atrakcyjnych i bogatych interfejsów. Twoja opinia jest dla nas bardzo ważna, dlatego podziel się nią na temat tych zmian lub tego, co Twoim zdaniem powinniśmy wprowadzić w przyszłości, w naszym systemie śledzenia problemów.

Czytaj dalej