Berita Produk

Yang baru di rilis Jetpack Compose Desember '25

Waktu baca: 6 menit
Nick Butcher
Product Manager

Hari ini, rilis Jetpack Compose Desember ‘25 sudah stabil. Rilis ini berisi modul inti Compose versi 1.10 dan Material 3 versi 1.4 (lihat pemetaan BOM lengkap), yang menambahkan fitur baru dan peningkatan performa yang signifikan.

Untuk menggunakan rilis hari ini, upgrade versi BOM Compose Anda ke 2025.12.00:

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

Peningkatan performa

Kami tahu bahwa performa runtime aplikasi Anda sangat penting bagi Anda dan pengguna Anda, jadi performa telah menjadi prioritas utama bagi tim Compose. Rilis ini menghadirkan sejumlah peningkatan—dan Anda bisa mendapatkan semuanya hanya dengan mengupgrade ke versi terbaru. Tolok ukur scroll internal kami menunjukkan bahwa Compose kini cocok dengan performa yang akan Anda lihat jika menggunakan View:

janky.png

Tolok ukur performa scroll yang membandingkan View dan Jetpack Compose di berbagai versi Compose

Komposisi yang dapat dijeda dalam pengambilan data awal lambat

Komposisi yang dapat dijeda dalam pengambilan data lambat kini diaktifkan secara default. Ini adalah perubahan mendasar pada cara kerja penjadwalan runtime Compose, yang dirancang untuk mengurangi jank secara signifikan selama workload UI yang berat.

Sebelumnya, setelah komposisi dimulai, komposisi harus dijalankan hingga selesai. Jika komposisi rumit, hal ini dapat memblokir thread utama lebih lama dari satu frame, sehingga menyebabkan UI membeku. Dengan komposisi yang dapat dijeda, runtime kini dapat "menjeda" pekerjaannya jika kehabisan waktu dan melanjutkan pekerjaan di frame berikutnya. Hal ini sangat efektif jika digunakan dengan pengambilan data tata letak lambat untuk menyiapkan frame sebelumnya. API CacheWindow tata letak Lazy yang diperkenalkan di Compose 1.9 adalah cara yang bagus untuk melakukan pengambilan data lebih awal dan memanfaatkan komposisi yang dapat dijeda untuk menghasilkan performa UI yang jauh lebih lancar.

pausable.gif

Komposisi yang dapat dijeda yang dikombinasikan dengan pengambilan data lazy membantu mengurangi jank

Kami juga telah mengoptimalkan performa di tempat lain, dengan peningkatan pada Modifier.onPlacedModifier.onVisibilityChanged, dan implementasi pengubah lainnya. Kami akan terus berinvestasi untuk meningkatkan performa Compose.

Fitur baru

Retain

Compose menawarkan sejumlah API untuk menyimpan dan mengelola status di seluruh siklus proses yang berbeda; misalnya, remember mempertahankan status di seluruh komposisi, dan rememberSavable/rememberSerializable untuk mempertahankan status di seluruh pembuatan ulang aktivitas atau proses. retain adalah API baru yang berada di antara API ini, yang memungkinkan Anda mempertahankan nilai di seluruh perubahan konfigurasi tanpa diserialisasi, tetapi tidak di seluruh proses dihentikan. Karena retain tidak melakukan serialisasi status Anda, Anda dapat mempertahankan objek seperti ekspresi lambda, flow, dan objek besar seperti bitmap, yang tidak dapat diserialisasi dengan mudah. Misalnya, Anda dapat menggunakan retain untuk mengelola pemutar media (seperti ExoPlayer) guna memastikan pemutaran media tidak terganggu oleh perubahan konfigurasi.

  @Composable

fun MediaPlayer() {

    val applicationContext = LocalContext.current.applicationContext

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

    ...

}

Kami ingin menyampaikan terima kasih kepada komunitas AndroidDev (terutama tim Circuit), yang telah memengaruhi dan berkontribusi pada desain fitur ini.

Material 1.4

Library material3 versi 1.4.0 menambahkan sejumlah komponen dan peningkatan baru:

centered-hero-carousel.webp

Carousel hero berpusat horizontal

Perhatikan bahwa API Material 3 Expressive terus dikembangkan dalam rilis alfa library material3. Untuk mempelajari lebih lanjut, lihat ceramah terbaru ini:

Fitur animasi baru

Kami terus memperluas API animasi kami, termasuk update untuk menyesuaikan animasi elemen bersama.

Elemen bersama dinamis

Secara default, animasi sharedElement() dan sharedBounds() mencoba menganimasikan

tata letak berubah setiap kali kunci yang cocok ditemukan dalam status target. Namun, Anda mungkin ingin menonaktifkan animasi ini secara dinamis berdasarkan kondisi tertentu, seperti arah navigasi atau status UI saat ini.

Untuk mengontrol apakah transisi elemen bersama terjadi, Anda kini dapat menyesuaikan SharedContentConfig yang diteruskan ke rememberSharedContentState(). Properti isEnabled menentukan apakah elemen bersama aktif.

  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

                }

            }

}

Lihat dokumentasi untuk mengetahui informasi selengkapnya.

Modifier.skipToLookaheadPosition()

Pengubah baru, Modifier.skipToLookaheadPosition(), telah ditambahkan dalam rilis ini, yang mempertahankan posisi akhir composable saat melakukan animasi elemen bersama. Hal ini memungkinkan transisi seperti animasi jenis “muncul”, seperti yang dapat dilihat dalam contoh Androidify dengan kemunculan progresif kamera. Lihat tips video di sini untuk mengetahui informasi selengkapnya: 

Kecepatan awal dalam transisi elemen bersama

Rilis ini menambahkan API transisi elemen bersama baru, prepareTransitionWithInitialVelocity, yang memungkinkan Anda meneruskan kecepatan awal (misalnya dari gestur) ke transisi elemen bersama:

  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

Transisi elemen bersama yang dimulai dengan kecepatan awal dari gestur

Transisi tertutup

EnterTransition dan ExitTransition menentukan cara composable AnimatedVisibility/AnimatedContent muncul atau menghilang. Opsi tabir eksperimental baru memungkinkan Anda menentukan warna untuk menutupi atau menyaring konten; misalnya, memudarkan lapisan hitam semi-transparan ke dalam/keluar konten:

veil_2.gif

Konten animasi yang tertutup – perhatikan tabir (atau scrim) semi-buram di atas konten petak selama animasi

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

    ...

}

Perubahan mendatang

Penghentian penggunaan Modifier.onFirstVisible

Compose 1.9 memperkenalkan Modifier.onVisibilityChanged dan Modifier.onFirstVisible. Setelah meninjau masukan Anda, kami menyadari bahwa kontrak Modifier.onFirstVisible tidak dapat dipenuhi secara deterministik; khususnya, saat item pertama menjadi terlihat. Misalnya, tata letak Lazy dapat menghapus item yang di-scroll keluar dari area tampilan, lalu menyusunnya kembali jika di-scroll kembali ke dalam tampilan. Dalam situasi ini, callback onFirstVisible akan diaktifkan lagi, karena merupakan item yang baru disusun. Perilaku serupa juga akan terjadi saat kembali ke layar yang sebelumnya dikunjungi yang berisi onFirstVisible. Oleh karena itu, kami telah memutuskan untuk menghentikan penggunaan pengubah ini dalam rilis Compose berikutnya (1.11) dan merekomendasikan migrasi ke onVisibilityChanged. Lihat dokumentasi untuk mengetahui informasi selengkapnya.

Pengiriman coroutine dalam pengujian

Kami berencana mengubah pengiriman coroutine dalam pengujian untuk mengurangi ketidakstabilan pengujian dan menemukan lebih banyak masalah. Saat ini, pengujian menggunakan UnconfinedTestDispatcher, yang berbeda dengan perilaku produksi; misalnya, efek dapat langsung berjalan, bukan dimasukkan dalam antrean. Dalam rilis mendatang, kami berencana memperkenalkan API baru yang menggunakan StandardTestDispatcher secara default agar sesuai dengan perilaku produksi. Anda dapat mencoba perilaku baru sekarang di 1.10:

  @get:Rule // also createAndroidComposeRule, createEmptyComposeRule

val rule = createComposeRule(effectContext = StandardTestDispatcher())

Penggunaan StandardTestDispatcher akan mengantrekan tugas, jadi Anda harus menggunakan mekanisme sinkronisasi seperti composeTestRule.waitForIdle() atau composeTestRule.runOnIdle(). Jika pengujian Anda menggunakan runTest, Anda harus memastikan bahwa runTest dan aturan Compose Anda menggunakan instance StandardTestDispatcher yang sama untuk sinkronisasi.

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

}

Alat

API yang hebat layak mendapatkan alat yang hebat, dan Android Studio memiliki sejumlah tambahan terbaru untuk developer Compose:

Untuk melihat cara kerja alat ini, tonton demonstrasi terbaru ini:

Selamat Belajar Menulis Kode

Kami terus berinvestasi di Jetpack Compose untuk menyediakan API dan alat yang Anda perlukan guna membuat UI yang menarik dan kaya. Kami menghargai masukan Anda, jadi sampaikan masukan Anda tentang perubahan ini atau apa yang ingin Anda lihat selanjutnya di pelacak masalah kami.

Ditulis oleh:

Lanjutkan membaca