Saat dihadapkan dengan class tidak stabil yang menyebabkan performa terjadi, Anda harus membuatnya stabil. Dokumen ini menguraikan beberapa teknik yang dapat untuk melakukannya.
Aktifkan pengabaian yang kuat
Pertama-tama, Anda harus mencoba mengaktifkan mode lewati yang kuat. Mode melewati yang ketat memungkinkan composable dengan parameter yang tidak stabil untuk dilewati dan merupakan cara termudah untuk memperbaiki masalah performa yang disebabkan oleh stabilitas.
Lihat Pelewatan yang ketat untuk informasi selengkapnya.
Membuat class tidak dapat diubah
Anda juga dapat mencoba membuat class yang tidak stabil sepenuhnya tidak dapat diubah.
- Tidak dapat diubah: Menunjukkan jenis nilai properti yang tidak dapat diubah
berubah setelah instance dari jenis tersebut dibuat, dan semua metode
transparan secara referensial.
- Pastikan semua properti class adalah
val
dan bukanvar
, dan jenis yang tidak dapat diubah. - Jenis primitif seperti
String, Int
, danFloat
selalu tidak dapat diubah. - Jika tidak memungkinkan, Anda harus menggunakan status Compose untuk properti yang dapat berubah.
- Pastikan semua properti class adalah
- Stabil: Menunjukkan jenis yang dapat diubah. Runtime Compose tidak mengetahui jika dan kapan salah satu properti atau metode publik jenis tersebut akan memberikan hasil yang berbeda dari pemanggilan sebelumnya.
Koleksi yang tidak dapat diubah
Alasan umum mengapa Compose menganggap class tidak stabil adalah koleksi. Seperti yang disebutkan
di halaman Diagnosis masalah stabilitas, compiler Compose
tidak dapat sepenuhnya yakin bahwa koleksi seperti List, Map
, dan Set
benar-benar tidak dapat diubah dan karena
itu menandainya sebagai tidak stabil.
Untuk mengatasi hal ini, Anda dapat menggunakan koleksi yang tidak dapat diubah. Compiler Compose mencakup dukungan untuk Koleksi yang Tidak Dapat Diubah Kotlinx. Ini koleksi dijamin tidak dapat diubah, dan compiler Compose akan memperlakukannya dengan demikian. Library ini masih dalam versi alfa, jadi kemungkinan akan ada perubahan pada API-nya.
Pertimbangkan lagi class yang tidak stabil ini dari kursus Diagnostik stabilitas panduan masalah:
unstable class Snack {
…
unstable val tags: Set<String>
…
}
Anda dapat membuat tags
stabil menggunakan koleksi yang tidak dapat diubah. Di kelas, ubah
jenis tags
hingga ImmutableSet<String>
:
data class Snack{
…
val tags: ImmutableSet<String> = persistentSetOf()
…
}
Setelahnya, semua parameter class tidak dapat diubah, dan Compose compiler menandai class sebagai stabil.
Anotasi dengan Stable
atau Immutable
Jalur yang mungkin untuk menyelesaikan masalah stabilitas adalah dengan menganotasi class yang tidak stabil
dengan @Stable
atau @Immutable
.
Menganotasi class menggantikan apa yang akan dilakukan compiler
simpulkan kelas Anda. Hal ini mirip dengan
Operator !!
di Kotlin. Anda harus sangat
berhati-hati tentang cara Anda
menggunakan anotasi tersebut. Mengganti perilaku compiler
dapat menyebabkan bug yang tidak terduga, seperti composable Anda yang tidak merekomposisi saat
yang Anda harapkan.
Jika memungkinkan untuk membuat class Anda stabil tanpa anotasi, Anda harus berusaha mencapai stabilitas dengan cara itu.
Cuplikan berikut memberikan contoh minimal dari class data yang dianotasi sebagai tidak dapat diubah:
@Immutable
data class Snack(
…
)
Baik Anda menggunakan anotasi @Immutable
atau @Stable
, compiler Compose
menandai class Snack
sebagai stabil.
Class yang dianotasi dalam koleksi
Pertimbangkan composable yang menyertakan parameter jenis List<Snack>
:
restartable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
…
unstable snacks: List<Snack>
…
)
Meskipun Anda menganotasi Snack
dengan @Immutable
, compiler Compose tetap menandai
parameter snacks
di HighlightedSnacks
sebagai tidak stabil.
Parameter menghadapi masalah yang sama dengan class dalam hal jenis koleksi,
Compiler Compose selalu menandai parameter jenis List
sebagai tidak stabil, bahkan
jika itu adalah kumpulan jenis stabil.
Anda tidak dapat menandai tiap parameter sebagai stabil, dan Anda juga tidak dapat menganotasikan dapat selalu dilewati. Ada beberapa jalur ke depan.
Ada beberapa cara untuk mengatasi masalah koleksi yang tidak stabil. Subbagian berikut menguraikan berbagai pendekatan tersebut.
File konfigurasi
Jika Anda bersedia mematuhi kontrak stabilitas di codebase Anda, maka
Anda dapat memilih untuk mempertimbangkan koleksi Kotlin sebagai stabil dengan menambahkan
kotlin.collections.*
ke
file konfigurasi stabilitas.
Koleksi yang tidak dapat diubah
Untuk keamanan waktu kompilasi dari ketetapan, Anda dapat
menggunakan koleksi yang tidak dapat diubah kotlinx, bukan List
.
@Composable
private fun HighlightedSnacks(
…
snacks: ImmutableList<Snack>,
…
)
Wrapper
Jika tidak dapat menggunakan koleksi yang tidak dapat diubah, Anda dapat membuatnya sendiri. Untuk melakukannya,
menggabungkan List
dalam class stabil yang dianotasi. Wrapper umum kemungkinan adalah
pilihan terbaik untuk ini, bergantung pada kebutuhan Anda.
@Immutable
data class SnackCollection(
val snacks: List<Snack>
)
Anda kemudian dapat menggunakannya sebagai jenis parameter dalam composable.
@Composable
private fun HighlightedSnacks(
index: Int,
snacks: SnackCollection,
onSnackClick: (Long) -> Unit,
modifier: Modifier = Modifier
)
Solusi
Setelah melakukan salah satu pendekatan ini, compiler Compose kini menandai
HighlightedSnacks
Composable sebagai skippable
dan restartable
.
restartable skippable scheme("[androidx.compose.ui.UiComposable]") fun HighlightedSnacks(
stable index: Int
stable snacks: ImmutableList<Snack>
stable onSnackClick: Function1<Long, Unit>
stable modifier: Modifier? = @static Companion
)
Selama rekomposisi, Compose sekarang dapat melewati HighlightedSnacks
jika tidak ada
input telah berubah.
File konfigurasi stabilitas
Mulai dari Compose Compiler 1.5.5, file konfigurasi class untuk
stabil dapat diberikan pada waktu kompilasi. Hal ini memungkinkan
untuk mempertimbangkan
class yang tidak Anda kontrol, seperti class library standar
seperti LocalDateTime
, sebagai stabil.
File konfigurasi adalah file teks biasa dengan satu class per baris. Komentar, karakter pengganti tunggal, dan ganda juga didukung. Contoh konfigurasi ditunjukkan di bawah ini:
// Consider LocalDateTime stable
java.time.LocalDateTime
// Consider kotlin collections stable
kotlin.collections.*
// Consider my datalayer and all submodules stable
com.datalayer.**
// Consider my generic type stable based off it's first type parameter only
com.example.GenericClass<*,_>
Untuk mengaktifkan fitur ini, teruskan jalur file konfigurasi ke kolom Compose opsi compiler.
Groovy
kotlinOptions {
freeCompilerArgs += [
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
project.absolutePath + "/compose_compiler_config.conf"
]
}
Kotlin
kotlinOptions {
freeCompilerArgs += listOf(
"-P",
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
"${project.absolutePath}/compose_compiler_config.conf"
)
}
Karena compiler Compose berjalan pada setiap modul dalam project secara terpisah, Anda dapat menyediakan konfigurasi yang berbeda untuk modul yang berbeda jika diperlukan. Atau, miliki satu di level root project Anda dan teruskan jalur tersebut ke ruang lingkup modul ini.
Beberapa modul
Masalah umum lainnya melibatkan arsitektur multi-modul. Compiler Compose hanya bisa menyimpulkan apakah suatu class stabil jika semua jenis non-primitif yang referensinya ditandai secara eksplisit sebagai stabil atau dalam modul yang juga dibuat dengan compiler Compose.
Jika lapisan data Anda berada dalam modul terpisah dari lapisan UI, yang merupakan pendekatan yang disarankan, ini mungkin menjadi masalah yang Anda temui.
Solusi
Untuk mengatasi masalah ini, Anda dapat melakukan salah satu pendekatan berikut:
- Tambahkan class ke file konfigurasi Compiler Anda.
- Mengaktifkan compiler Compose di modul lapisan data atau memberi tag pada class
dengan
@Stable
atau@Immutable
, jika sesuai.- Hal ini melibatkan penambahan dependensi Compose ke lapisan data Anda. Namun,
hanya dependensi untuk runtime Compose dan bukan untuk
Compose-UI
.
- Hal ini melibatkan penambahan dependensi Compose ke lapisan data Anda. Namun,
hanya dependensi untuk runtime Compose dan bukan untuk
- Dalam modul UI, gabungkan class lapisan data dalam wrapper khusus UI Google Cloud Platform.
Masalah yang sama juga terjadi saat menggunakan {i>library<i} eksternal jika mereka tidak menggunakan Compiler Compose.
Tidak semua composable harus dapat dilewati
Saat berupaya memperbaiki masalah stabilitas, Anda tidak boleh mencoba setiap dan dapat dilewati. Mencoba melakukan hal itu dapat menyebabkan pengoptimalan dini yang menimbulkan lebih banyak masalah daripada perbaikannya.
Ada banyak situasi ketika iklan yang dapat dilewati tidak memiliki manfaat nyata dan dapat menyebabkan kode yang sulit dikelola. Contoh:
- Composable yang tidak sering direkomposisi, atau sama sekali.
- Composable yang hanya memanggil composable yang dapat dilewati.
- Composable dengan sejumlah besar parameter dengan persamaan yang mahal implementasi yang tepat. Dalam hal ini, biaya untuk memeriksa apakah parameter memiliki dapat lebih besar dibandingkan biaya rekomposisi yang murah.
Jika composable dapat dilewati, composable tersebut akan menambahkan overhead kecil yang mungkin tidak berharga anotasi. Anda bahkan dapat menganotasi composable menjadi tidak dapat dimulai ulang jika terjadi di mana Anda menentukan bahwa dapat dilakukan {i>restart<i} membutuhkan lebih banyak {i>overhead<i} daripada manfaatnya.