Jika Anda terjun ke dunia Android, Anda pasti pernah menghadapi dilema abadi tentang bagaimana menangani data di lapisan presentasi. Untuk waktu yang lama, LiveData mendominasi, tetapi dengan hadirnya coroutine Kotlin, alat yang jauh lebih ampuh dan fleksibel telah muncul. Kita berbicara tentang StateFlow dan SharedFlow , yang pada dasarnya merupakan evolusi alami untuk mengelola aliran data secara reaktif dan efisien.
Sebenarnya, meskipun pada awalnya konsep-konsep ini tampak serupa, masing-masing memiliki tujuan tersendiri. Menginginkan layar untuk mengingat di mana umpan berita terakhir ditampilkan tidak sama dengan menginginkan pemberitahuan singkat untuk Toast yang hanya perlu dilihat sekali. Untuk menghindari kebingungan, mari kita uraikan bagaimana aliran data instan ini bekerja dan mengapa Anda harus mempertimbangkan untuk meninggalkan LiveData dalam proyek modern Anda.
Konsep Flow: Dingin atau Panas?
Untuk memahami StateFlow dan SharedFlow, Anda perlu memahami perbedaan antara alur dingin dan alur panas terlebih dahulu. Alur standar bersifat dingin , artinya seperti resep: tidak ada yang terjadi sampai seseorang memutuskan untuk menjalankannya (memanggil `collect`). Masalahnya adalah jika Anda memiliki tiga pelanggan, kode produsen akan dieksekusi tiga kali, yang dapat menguras baterai atau membuat permintaan API yang berlebihan.
Di sinilah hot stream berperan. Baik StateFlow maupun SharedFlow secara strategis bersifat hot , artinya produsen tetap aktif terlepas dari apakah ada yang mendengarkan atau tidak. Hal ini memungkinkan beberapa kolektor untuk berbagi sumber data yang sama , mencegah aplikasi melakukan pekerjaan yang sama berulang kali—penting untuk menjaga kelancaran sistem.
StateFlow: Pengganti ideal untuk LiveData
StateFlow pada dasarnya adalah sebuah wadah status. Fitur utamanya adalah selalu mempertahankan nilai terkini , yang dapat diakses secara sinkron menggunakan properti `.value`. Ini adalah alat yang sempurna untuk mengelola status antarmuka pengguna, seperti apakah layar sedang memuat atau apakah data profil telah berhasil diperbarui.
Tidak seperti LiveData, StateFlow membutuhkan nilai awal di konstruktornya, sehingga menghilangkan ketidakpastian karena adanya status null saat startup. Selain itu, ia menerapkan perilaku penggabungan dan penghapusan duplikasi : jika Anda memancarkan nilai yang sama dua kali berturut-turut, alur tersebut akan mengabaikannya. Ini sangat bagus untuk mencegah UI melakukan penyegaran yang tidak perlu ketika data sebenarnya tidak berubah.
Untuk mengimplementasikan ini di ViewModel, pendekatan terbaik adalah menggunakan properti fallback private MutableStateFlow dan mengeksposnya sebagai StateFlow yang tidak dapat diubah. Ini memastikan bahwa hanya ViewModel yang dapat mengubah status, menghormati aliran data searah dan mencegah tampilan memanipulasi data.
SharedFlow: Bus peristiwa untuk tindakan unik.
Jika StateFlow digunakan untuk "status," maka SharedFlow digunakan untuk "kejadian." Bayangkan Anda ingin menampilkan dialog kesalahan atau beralih ke layar lain. Jika Anda menggunakan StateFlow, memutar perangkat akan menyebabkan kolektor baru menerima nilai terakhir, dan kejadian tersebut akan terpicu lagi — sebuah bug serius. SharedFlow mengatasi hal ini karena dapat dikonfigurasi dengan nilai pemutaran ulang nol.
Alur ini jauh lebih fleksibel dan memungkinkan kita untuk menyesuaikan parameter seperti buffer luapan . Jika buffer penuh, kita dapat memilih untuk menangguhkan pengirim atau membuang nilai terlama atau terbaru. Keuntungan utama adalah SharedFlow memungkinkan Anda untuk mengirim nilai berulang ; jika Anda perlu mengirim pesan "Kesalahan Koneksi" yang sama tiga kali, SharedFlow akan melakukannya tanpa ragu-ragu, sedangkan StateFlow akan menyaringnya.
Perbandingan teknis: StateFlow vs SharedFlow vs LiveData
Untuk menghindari kebingungan dalam wawancara teknis atau saat mendesain arsitektur Anda, penting untuk mempertimbangkan poin-poin penting. LiveData sederhana dan mengelola siklus hidup secara otomatis , tetapi sangat terikat pada Android. StateFlow dan SharedFlow, sebagai bagian dari Kotlin Coroutines, bersifat independen platform , yang sangat menyederhanakan pengujian unit dan pembuatan lapisan domain yang bersih.
- StateFlow: Memaksa nilai awal, memiliki .value, menghilangkan nilai duplikat, dan ideal untuk status UI.
- SharedFlowFitur ini tidak memerlukan nilai awal, dapat dikonfigurasi dalam hal pemutaran ulang, dan merupakan pilihan yang tepat untuk peristiwa yang bersifat sementara.
- Data Langsung: Tidak memerlukan nilai awal, ia memahami siklus hidup tetapi kurang ampuh dalam transformasi asinkron.
Pentingnya panen yang aman
Kesalahan yang sangat umum adalah menjalankan `collect` dalam lingkup coroutine sederhana di Activity. Ini berbahaya karena alur akan terus memproses data bahkan ketika aplikasi berada di latar belakang , yang dapat menyebabkan crash atau penggunaan CPU yang berlebihan. Solusi modernnya adalah menggunakan API `repeatOnLifecycle(Lifecycle.State.STARTED)`.
Fungsi ini menyebabkan koleksi aktif ketika tampilan terlihat dan secara otomatis dibatalkan ketika mencapai status STOPPED . Untuk Jetpack Compose, rekomendasinya adalah menggunakan `collectAsStateWithLifecycle()` , yang mengintegrasikan logika ini secara native dan memastikan aplikasi efisien dalam penggunaan sumber daya perangkat.
Mengubah aliran dingin menjadi aliran panas
Terkadang kita memiliki alur yang berasal dari basis data (seperti Room) atau repositori, dan alur tersebut bersifat dingin. Untuk membuatnya panas, kita menggunakan operator `stateIn` atau `shareIn` . Operator ini memerlukan `CoroutineScope` dan strategi startup. Yang paling umum adalah `SharingStarted.WhileSubscribed(5000)`.
Konfigurasi ini sangat bagus karena menjaga aliran data tetap aktif selama masih ada pelanggan, dan jika layar ditutup, ia akan menunggu 5 detik sebelum menghentikan aliran data. Ini sangat penting agar, selama rotasi layar , aliran data tidak dihancurkan dan dibuat ulang, sehingga menghindari permintaan yang tidak perlu ke server atau basis data lokal.
Menguasai alat-alat ini melibatkan pemahaman bahwa status harus persisten dan dihilangkan duplikasinya menggunakan StateFlow, sementara tindakan sekali jalan harus mengalir melalui SharedFlow. Dengan menggabungkan ini dengan kesadaran siklus hidup dan transformasi alur dingin menggunakan stateIn, kita mencapai arsitektur Android yang tangguh dan sepenuhnya reaktif yang dioptimalkan untuk kinerja dunia nyata pada perangkat seluler. Bagikan panduan ini dan bantu orang lain mempelajari topik ini.
