Compose menganggap jenis sebagai stabil atau tidak stabil. Suatu jenis dikatakan stabil jika tidak dapat diubah, atau jika Compose dapat mengetahui apakah nilainya telah berubah saat rekomposisi. Suatu jenis dikatakan tidak stabil jika Compose tidak dapat mengetahui apakah nilainya telah berubah saat rekomposisi.
Compose menggunakan stabilitas parameter composable untuk menentukan cara membandingkan input dan memutuskan apakah composable dapat dilewati selama rekomposisi (dengan Mode strong skipping diaktifkan secara default mulai Kotlin 2.0.20):
- Parameter stabil: Compose membandingkan parameter stabil menggunakan kesetaraan
struktural (
Object.equals()). Jika parameter stabil composable sama dengan nilai sebelumnya, Compose akan melewati parameter tersebut. - Parameter tidak stabil: Dengan mengaktifkan Mode skipping kuat (default di Kotlin 2.0.20 dan yang lebih tinggi), Compose membandingkan parameter tidak stabil menggunakan kesetaraan instance (
===) dan melewati composable jika instance objek yang sama diteruskan. Dalam versi sebelum Kotlin 2.0.20 (atau saat mode Strong skipping dinonaktifkan), Compose selalu merekomposisi composable dengan parameter tidak stabil saat induknya melakukan rekomposisi.
Jika aplikasi Anda sering mengalokasikan instance baru dari parameter yang tidak stabil—atau memaksa
pemeriksaan .equals() yang mahal pada koleksi besar dengan menganotasi model secara berlebihan—Anda
mungkin akan mengamati rekomposisi atau overhead perbandingan yang tidak perlu.
Dokumen ini menjelaskan cara Compose menentukan stabilitas dan cara mengoptimalkannya untuk meningkatkan performa dan pengalaman pengguna secara keseluruhan.
Objek yang tidak dapat diubah
Cuplikan berikut menunjukkan prinsip umum di balik stabilitas dan rekomposisi.
Class Contact adalah class data yang tidak dapat diubah. Hal ini karena semua parameternya adalah primitif yang ditentukan dengan kata kunci val. Setelah membuat
instance Contact, Anda tidak dapat mengubah nilai properti objek.
Jika Anda mencoba melakukannya, Anda akan membuat objek baru.
data class Contact(val name: String, val number: String)
Composable ContactRow memiliki parameter jenis Contact.
@Composable
fun ContactRow(contact: Contact, modifier: Modifier = Modifier) {
var selected by remember { mutableStateOf(false) }
Row(modifier) {
ContactDetails(contact)
ToggleButton(selected, onToggled = { selected = !selected })
}
}
Pertimbangkan apa yang terjadi saat pengguna mengklik tombol beralih dan
status selected berubah:
- Compose mengevaluasi apakah kode di dalam
ContactRowharus direkomposisi. - Sistem akan melihat bahwa satu-satunya argumen untuk
ContactDetailsadalah jenisContact. - Karena
Contactadalah class data yang tidak dapat diubah, Compose yakin bahwa tidak ada argumen untukContactDetailsyang berubah. - Oleh karena itu, Compose akan melewati
ContactDetailsdan tidak merekomposisinya. - Di sisi lain, argumen untuk
ToggleButtontelah berubah, dan Compose merekomposisi komponen tersebut.
Objek yang dapat diubah
Meskipun contoh sebelumnya menggunakan objek yang tidak dapat diubah, Anda dapat membuat objek yang dapat diubah. Perhatikan cuplikan berikut:
data class Contact(var name: String, var number: String)
Karena setiap parameter Contact kini menjadi var, class tidak lagi tidak dapat diubah.
Jika propertinya berubah, Compose tidak akan mengetahuinya. Hal ini karena
Compose hanya melacak perubahan pada objek State Compose.
Compose menganggap class tersebut tidak stabil. Dengan Mode strong skipping
(Kotlin 2.0.20+), Compose membandingkan Contact menggunakan kesetaraan instance (===):
mengubah contact.name di tempat tidak akan memicu rekomposisi, sedangkan meneruskan
instance Contact yang baru dialokasikan dengan nilai yang sama akan tetap memaksa
ContactDetails untuk melakukan rekomposisi (dan tanpa Mode strong skipping,
ContactDetails melakukan rekomposisi setiap kali selected berubah).
Implementasi di Compose
Meskipun tidak terlalu penting, sebaiknya pertimbangkan cara Compose menentukan fungsi yang akan dilewati selama rekomposisi.
Saat berjalan pada kode Anda, compiler Compose menandai setiap fungsi dan jenis dengan salah satu dari beberapa tag. Tag ini mencerminkan cara Compose menangani fungsi atau jenis selama rekomposisi.
Fungsi
Compose dapat menandai fungsi sebagai skippable atau restartable. Perhatikan bahwa fungsi ini dapat
menandai fungsi sebagai salah satu, keduanya, atau tidak keduanya:
- Dapat dilewati: Jika compiler menandai composable sebagai dapat dilewati, Compose dapat melewatinya selama rekomposisi jika semua argumennya sama dengan nilai sebelumnya. (Dengan Mode strong skipping di Kotlin 2.0.20+, semua composable yang dapat dimulai ulang akan otomatis dapat dilewati.)
- Dapat dimulai ulang: Composable yang dapat dimulai ulang berfungsi sebagai "cakupan" tempat rekomposisi dapat dimulai. Dengan kata lain, fungsi ini dapat menjadi titik masuk tempat Compose dapat mulai mengeksekusi ulang kode untuk rekomposisi setelah perubahan status.
Jenis
Compose menandai jenis sebagai tidak dapat diubah atau stabil. Setiap jenis adalah salah satu dari berikut:
- Tidak dapat diubah: Compose menandai jenis sebagai tidak dapat diubah jika nilai
propertinya tidak pernah berubah dan semua metode transparan secara referensial.
- Perhatikan bahwa semua jenis primitif ditandai sebagai tidak dapat diubah. Ini termasuk
String,Int, danFloat.
- Perhatikan bahwa semua jenis primitif ditandai sebagai tidak dapat diubah. Ini termasuk
- Stable: Menunjukkan jenis yang propertinya dapat berubah setelah konstruksi. Jika dan saat properti tersebut berubah selama runtime, Compose akan mengetahui perubahan tersebut.
Men-debug stabilitas
Jika aplikasi Anda merekomposisi composable yang parameternya tidak berubah, periksa terlebih dahulu
apakah instance baru dari jenis yang tidak stabil dialokasikan pada setiap
rekomposisi (atau, jika mode Strong skipping dinonaktifkan, apakah composable
memiliki parameter dengan properti var atau properti val dari jenis yang tidak stabil).
Untuk mengetahui informasi mendetail tentang cara mendiagnosis masalah kompleks terkait stabilitas di Compose, lihat panduan Men-debug stabilitas.
Memperbaiki masalah stabilitas
Untuk mengetahui informasi tentang cara menghadirkan stabilitas pada implementasi Compose, lihat panduan Memperbaiki masalah stabilitas.
Ringkasan
Secara keseluruhan, Anda harus memperhatikan poin-poin berikut:
- Parameter: Compose menentukan stabilitas setiap parameter composable
Anda untuk memutuskan apakah akan membandingkannya menggunakan persamaan struktural
(
.equals()) atau persamaan instance (===) selama rekomposisi. - Perbaikan langsung: Jika Anda melihat composable tidak dilewati dan
menyebabkan masalah performa, periksa apakah instance baru parameter
yang tidak stabil dibuat ulang pada setiap penerusan atau apakah properti
vardigunakan, bukanState. - Laporan compiler: Anda dapat menggunakan laporan compiler untuk menentukan stabilitas yang disimpulkan tentang class Anda.
- Koleksi: Compose menganggap antarmuka koleksi standar (
List,Set, danMap) tidak stabil karena implementasi dasarnya mungkin berubah-ubah. Dengan Mode lewati kuat (diaktifkan secara default di Kotlin 2.0.20+), koleksi yang tidak stabil tetap melewati rekomposisi menggunakan kesetaraan instance (===) saat referensi koleksi tidak berubah. Berhati-hatilah saat mengganti koleksi standar dengan koleksi immutable Kotlinx atau menganotasi class yang menyimpan koleksi dengan@Immutableatau@Stable, karena membandingkan setiap elemen dengan.equals()pada setiap penerusan rekomposisi dapat lebih mahal daripada rekomposisi itu sendiri. - Modul lain: Compose menganggap class dari modul tempat compiler Compose tidak berjalan sebagai tidak stabil (dibandingkan menggunakan
===dalam Mode strong skipping). Jika sumber data sering membuat ulang instance model kecil dan datar dari modul non-Compose dengan nilai yang sama, Anda dapat mengonfigurasi file konfigurasi stabilitas atau menggunakan@Stableatau@Immutablejika.equals()murah.
Bacaan lebih lanjut
- Performa: Untuk tips proses debug lainnya tentang performa Compose, lihat panduan praktik terbaik dan diskusi I/O kami.