Recomposition — apa itu, pembangunan ulang UI saat perubahan status

Penulis: IT Sectr Diterbitkan: 2026-06-27 Waktu membaca: 7 mnt

Recomposition adalah mekanisme Jetpack Compose yang secara otomatis membangun ulang bagian-bagian antarmuka pengguna saat data berubah, tanpa pembaruan manual elemen View. Ketika variabel status yang bergantung pada fungsi Composable mengubah nilainya, Compose hanya menjalankan ulang fungsi tersebut, membiarkan sisa pohon UI tidak tersentuh. Menurut data Google Android Developers, 2026, pemahaman yang benar tentang Recomposition memungkinkan pengurangan jumlah penggambaran ulang yang tidak perlu sebesar 40–60%.

Poin utama

  • Recomposition — menjalankan ulang fungsi Composable saat data masukan atau State berubah
  • Skipping — melewatkan fungsi yang parameternya tidak berubah (perbandingan melalui equals)
  • Stability menentukan apakah Compose dapat melewatkan fungsi — tipe stabil dibandingkan dengan benar
  • Smart Recomposition hanya menjalankan ulang set fungsi minimum, bukan seluruh pohon
  • Rekomposisi tidak menjamin penggambaran ulang — Layout dan Drawing dapat melewatkan fase

Apa itu Recomposition di Jetpack Compose

Recomposition adalah eksekusi ulang fungsi Composable yang sudah berpartisipasi dalam Composition, dengan nilai baru parameter atau status. Tujuan utama rekomposisi adalah menyinkronkan pohon UI dengan data terkini tanpa membangun ulang seluruh antarmuka dari awal. Tidak seperti Composition yang terjadi sekali, Recomposition dapat dijalankan ratusan kali selama masa pakai layar.

Recomposition bekerja berdasarkan prinsip smart invalidation: Compose melacak objek State mana yang dibaca oleh setiap fungsi Composable dan menandai untuk dijalankan ulang hanya fungsi-fungsi yang dependensinya berubah. Ini dicapai melalui sistem snapshot, yang mencatat semua operasi pembacaan State selama eksekusi, dan Composer, yang memetakan dependensi ini ke fungsi-fungsi tertentu.

Penting untuk dipahami: rekomposisi tidak berarti penggambaran ulang layar secara instan. Compose bekerja dalam tiga fase: Composition (membangun deskripsi UI), Layout (menghitung ukuran dan posisi) dan Drawing (menggambar di kanvas). Jika setelah rekomposisi ukuran dan posisi elemen tidak berubah, fase Layout dapat dilewati. Jika tampilan tidak berubah — Drawing dilewati. Arsitektur tiga fase ini memastikan biaya minimal setiap pembaruan UI.

Pemicu rekomposisi: apa yang menyebabkan menjalankan ulang fungsi

Ada tiga pemicu utama rekomposisi. Pertama — perubahan objek State yang dibaca di dalam tubuh fungsi Composable. Ketika mutableStateOf atau derivedStateOf mengubah nilainya, semua fungsi yang mencatat pembacaan State ini dalam komposisi sebelumnya ditandai untuk dijalankan ulang.

Pemicu kedua — perubahan parameter fungsi Composable saat dipanggil dari fungsi induk. Jika fungsi induk memberikan nilai baru (misalnya teks atau angka berubah), fungsi anak akan dijalankan ulang, meskipun tidak membaca State di dalamnya. Compose membandingkan nilai baru dan lama parameter melalui equals, dan jika sama — fungsi dapat dilewati.

Pemicu ketiga — perubahan CompositionLocal melalui CompositionLocalProvider. Semua fungsi yang membaca CompositionLocal melalui .current dijalankan ulang saat provider berubah. Mekanisme ini digunakan oleh MaterialTheme: perubahan tema (terang/gelap) menyebabkan rekomposisi semua komponen yang membaca MaterialTheme.colorScheme.

kotlin
@Composable
fun RecompositionDemo() {
    var counter by remember { mutableStateOf(0) }
    var text by remember { mutableStateOf("Hello") }

    Column {
        Text("Penghitung: $counter")  // rekomposisi saat penghitung berubah
        Text("Pesan: $text")    // rekomposisi saat teks berubah

        Button(onClick = { counter++ }) {
            Text("+1")
        }
        Button(onClick = { text = "Dunia" }) {
            Text("Ubah teks")
        }
    }
}

Menekan tombol +1 mengubah counter, yang menyebabkan rekomposisi hanya pada baris Text pertama dan Column itu sendiri. Baris Text kedua, yang menampilkan text, tidak dijalankan ulang. Isolasi semacam itu — hasil dari sistem snapshot: setiap fungsi Composable hanya tahu tentang objek State yang telah dibacanya.

Optimasi rekomposisi: teknik praktis

Optimasi rekomposisi dimulai dengan pemilihan struktur data yang tepat. Gunakan koleksi tak-terubah (listOf, mapOf) alih-alih koleksi yang dapat diubah (mutableListOf). Compose membandingkan parameter melalui equals, dan jika koleksi berubah tetapi equals mengembalikan true — fungsi tidak akan dijalankan ulang. Untuk koleksi yang dapat diubah, gunakan SnapshotStateList, yang mengimplementasikan pelacakan perubahan yang benar di tingkat elemen.

Teknik kedua — memisahkan bagian stabil UI ke dalam fungsi Composable terpisah. Jika bagian layar tidak bergantung pada status yang sering berubah, pisahkan ke dalam fungsi terpisah dengan parameter. Ketika rekomposisi datang, fungsi stabil menerima parameter yang sama, Compose membandingkannya dan melewatkan eksekusi. Ini lebih menguntungkan daripada menjalankan ulang bagian ini dalam fungsi besar di mana sebagian parameternya berubah.

Teknik ketiga — kunci di LazyColumn. Selalu berikan key untuk item di LazyColumn, LazyGrid, dan wadah malas lainnya. Kunci memungkinkan Compose mengidentifikasi elemen saat daftar berubah: penambahan, penghapusan, atau penataan ulang. Tanpa kunci, Compose menjalankan ulang semua elemen daftar pada setiap perubahan, yang pada daftar besar memberikan penurunan kinerja yang signifikan.

kotlin
// Struktur yang dioptimalkan: bagian stabil dipisahkan secara terpisah
@Composable
fun OptimizedScreen(items: List<Item>) {
    Column {
        Header()                         // tidak tergantung pada item — tidak ada rekomposisi
        Spacer(modifier = Modifier.height(8.dp))
        LazyColumn {
            items(items, key = { it.id }) { item ->
                ItemRow(item = item)   // rekomposisi hanya untuk item yang berubah
            }
        }
    }
}

@Composable
fun Header() {
    Text("Daftar item", style = MaterialTheme.typography.headlineMedium)
}

@Composable
fun ItemRow(item: Item) {
    Text(item.title)
}

Skipping dan Stability di Compose

Skipping adalah mekanisme di mana Compose melewatkan eksekusi fungsi Composable jika semua parameternya tidak berubah. Agar skipping berfungsi dengan benar, tipe parameter harus stabil (stable). Kompiler Kotlin menandai sebagai stabil: tipe primitif (Int, Float, Boolean), String, fungsi lambda, serta kelas yang semua bidangnya stabil dan val.

Stability adalah anotasi @Stable atau @Immutable yang dapat ditambahkan ke kelas data kustom. Jika kelas berisi bidang yang dapat diubah (var), kompiler menganggapnya tidak stabil dan Compose tidak dapat melewatkan fungsi dengan parameter semacam itu. Untuk kelas dengan var, gunakan @Stable jika Anda menjamin bahwa pemberitahuan tentang perubahan akan dikirim melalui sistem snapshot.

Stability dapat diperiksa melalui flag kompiler -P "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=. /reports". Ini menghasilkan laporan dengan daftar semua fungsi Composable dan parameternya dengan indikasi stability. Jika parameter tidak stabil — skipping untuk fungsi itu tidak mungkin dan akan dijalankan ulang pada setiap rekomposisi induk.

TipeStabilitasSkipping
Int, Float, BooleanStabilYa
StringStabilYa
LambdaStabilYa
data class dengan bidang valStabilYa
data class dengan bidang varTidak stabilTidak
List<String>Tidak stabilTidak

Perhatikan: List<String> dianggap tidak stabil karena ini adalah antarmuka, bukan implementasi konkret. Gunakan immutableListOf() dari pustaka Kotlin Collections Immutable atau bungkus daftar dalam kelas @Stable. Lambda selalu stabil, karena equals-nya hanya membandingkan referensi, dan saat membuat lambda baru di lokasi pemanggilan, fungsi induk juga dijalankan ulang.

Pemantauan rekomposisi di Android Studio

Untuk pemantauan rekomposisi, Android Studio menyediakan Layout Inspector dengan mode Compose Recomposition Counts. Dalam mode ini, setiap fungsi Composable menampilkan jumlah rekomposisi dan alasan menjalankan ulang. Ini memungkinkan dengan cepat menemukan fungsi yang terlalu sering direkomposisi dan menentukan akar penyebab — parameter tidak stabil atau dependensi State yang tidak perlu.

Alat tambahan: Compose Metrics (mengumpulkan statistik melalui tes instrumentation) dan Recomposition Timer (mengukur waktu eksekusi setiap fungsi). Google merekomendasikan mengaktifkan alat-alat ini pada tahap profiling dan menonaktifkannya di rilis produksi, karena mereka menambahkan overhead hingga 20% pada setiap rekomposisi.

Saat menganalisis rekomposisi, cari pola unnecessary recomposition: fungsi dijalankan ulang meskipun UI keluarannya seharusnya tidak berubah. Penyebab umum adalah penggunaan lambda tanpa remember, ketika setiap kali objek lambda baru dibuat dan Compose menganggap parameter berubah. Solusi: membungkus lambda dalam remember { } dengan tangkapan tetap.

kotlin
// Buruk: lambda baru pada setiap rekomposisi induk
@Composable
fun Parent() {
    Child(onClick = { doSomething() })  // lambda baru setiap kali
}

// Baik: remember menstabilkan lambda
@Composable
fun Parent() {
    val onClick = remember { { doSomething() } }
    Child(onClick = onClick)  // referensi yang sama
}

Pertanyaan yang sering diajukan

Apakah rekomposisi berarti penggambaran ulang layar?

Tidak, rekomposisi hanya fase Composition. Setelahnya Layout dan Drawing dijalankan. Jika setelah rekomposisi ukuran dan posisi elemen tidak berubah, Layout dan Drawing dapat sepenuhnya dilewati, yang menghemat sumber daya GPU.

Seberapa sering rekomposisi dapat terjadi?

Pada animasi, rekomposisi dapat dijalankan hingga 120 kali per detik (120fps). Untuk interaksi biasa — 10–60 kali per detik. Penting agar setiap rekomposisi masuk dalam anggaran bingkai (8–16 ms), jika tidak aplikasi akan melambat.

Mengapa fungsi direkomposisi meskipun State tidak berubah?

Penyebabnya — perubahan parameter dari fungsi induk. Induk dijalankan ulang (karena alasannya sendiri) dan memberikan nilai baru. Untuk menghindari ini, periksa stability parameter dan gunakan remember untuk stabilisasi lambda dan nilai yang dihitung.

Bisakah rekomposisi dinonaktifkan untuk fungsi tertentu?

Tidak ada penonaktifan langsung, tetapi ada skipping paksa melalui readInComposition — State dibaca di luar tubuh fungsi, yang tidak mendaftarkan dependensi. Gunakan ini dengan hati-hati: fungsi tidak akan merespons perubahan, yang dapat menyebabkan UI usang.

Mana yang lebih mahal: Composition atau Recomposition?

Composition lebih mahal karena membuat semua slot dan simpul pohon dari awal. Recomposition menggunakan kembali slot yang ada dan hanya memperbarui nilainya. Dalam praktiknya, Composition layar membutuhkan waktu 2–10 ms, dan rekomposisi satu elemen — 0.1–1 ms.

Kesimpulan

  • Recomposition — menjalankan ulang selektif fungsi Composable saat State atau parameter berubah
  • Snapshot system melacak dependensi fungsi terhadap State dan merencanakan rekomposisi
  • Skipping hanya mungkin untuk fungsi dengan parameter stabil (@Stable atau immutable)
  • Tiga pemicu rekomposisi: perubahan State, perubahan parameter, perubahan CompositionLocal
  • List<T> dianggap tidak stabil — gunakan koleksi tak-terubah untuk skipping yang benar
  • Layout Inspector menunjukkan penghitung rekomposisi untuk setiap fungsi
  • Rekomendasi: pisahkan bagian stabil UI ke dalam fungsi terpisah dan gunakan remember untuk lambda

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga