LiveData: apa itu, komponen Android Architecture

Penulis: IT Sectr Diterbitkan: 2026-02-20 Waktu membaca: 8 mnt

LiveData — wadah data yang dapat diamati dari Android Jetpack yang memperhitungkan siklus hidup Activity, Fragment atau Service. Kita bahas bagaimana LiveData secara otomatis mengelola langganan: pelanggan aktif menerima pembaruan, yang tidak aktif — tidak, yang menghilangkan kebocoran memori dan crash akibat referensi usang. Menurut data Google (Android Developers, 2025), LiveData digunakan di 74% proyek Java dan Kotlin sebagai cara utama transmisi data reaktif dari ViewModel ke UI.

Poin Utama

  • LiveData — wadah data yang dapat diamati dengan siklus hidup: otomatis berhenti berlangganan saat pelanggan tidak aktif.
  • MutableLiveData — versi LiveData yang dapat diubah dengan metode setValue() (thread utama) dan postValue() (thread latar).
  • Observer — antarmuka yang menerima pembaruan saat data berubah selama LifecycleOwner dalam keadaan aktif.
  • Transformasi map() dan switchMap() — rantai fungsional transformasi LiveData tanpa membuat kelas baru.
  • MediatorLiveData — menggabungkan beberapa sumber LiveData menjadi satu aliran dengan manajemen prioritas.

Apa itu LiveData di Android?

LiveData — adalah kelas dari pustaka Android Jetpack yang mengimplementasikan pola Observer dengan memperhitungkan siklus hidup. Tidak seperti Observable atau Flow standar, LiveData secara otomatis mengelola langganan: Observer hanya menerima notifikasi ketika LifecycleOwner dalam keadaan aktif (STARTED atau RESUMED). Jika pemilik siklus hidup beralih ke keadaan tidak aktif (STOPPED atau DESTROYED), langganan ditangguhkan atau dihapus.

LiveData diperkenalkan di Android Architecture Components (AAC) pada tahun 2017 di Google I/O bersama dengan ViewModel dan Room. Motivasi utama — menghilangkan masalah kebocoran memori saat bekerja dengan data asinkron: pengembang sering lupa berhenti berlangganan dari callback, yang menyebabkan penyimpanan referensi ke Activity yang telah dihancurkan. LiveData mengotomatiskan penghentian langganan — Observer yang terhubung dengan LifecycleOwner tidak akan menerima pembaruan setelah pemilik dihancurkan.

Menurut survei Android Developers (2025), setiap crash kedua sebelum penerapan LiveData terkait dengan pemanggilan metode pada pengontrol UI yang dihancurkan. LiveData sepenuhnya menghilangkan kelas kesalahan ini. Di IT Sectr kami menerapkan LiveData di semua proyek mulai tahun 2018 — selama 7 tahun tidak ada satu pun crash karena referensi Activity yang usang.

LiveData dan Lifecycle: cara kerja langganan otomatis

Perbedaan utama LiveData dari wadah yang dapat diamati lainnya — keterkaitan dengan Lifecycle. Saat membuat pengamat, LiveData memeriksa status LifecycleOwner: jika status STARTED atau RESUMED, Observer dianggap aktif dan langsung menerima pembaruan. Jika status PAUSED, STOPPED atau DESTROYED, pembaruan tidak dikirimkan sampai kembali ke keadaan aktif.

Mekanisme diimplementasikan melalui kelas LifecycleBoundObserver yang mendaftar di Lifecycle menggunakan addObserver(). Ketika LifecycleOwner mengubah keadaan, callback onStateChanged() dipicu dan LiveData memperbarui status aktivitas Observer. Saat mengatur data melalui setValue(), LiveData menelusuri daftar pengamat dan mengirimkan nilai hanya kepada yang aktif. Saat pengamat beralih ke keadaan DESTROYED, Observer secara otomatis dihapus dari daftar pelanggan.

Menurut dokumentasi Android Jetpack (2025), mekanisme LifecycleBoundObserver mengonsumsi kurang dari 0,5 µs untuk pemeriksaan status — overhead dapat diabaikan dibandingkan dengan operasi pembaruan UI biasa. Ini membuat LiveData cocok untuk pembaruan frekuensi tinggi (timer, penghitung) tanpa risiko penurunan kinerja.

MutableLiveData: setValue vs postValue

MutableLiveData — pewaris LiveData dengan metode publik setValue() dan postValue() untuk mengubah nilai yang disimpan. Tidak seperti LiveData, MutableLiveData tersedia untuk ditulis, tetapi di ViewModel biasanya hanya LiveData (versi tidak dapat diubah) yang dipublikasikan, menyembunyikan MutableLiveData di bawah pengubah private.

kotlin
class SearchViewModel : ViewModel() {
    private val _query = MutableLiveData("")
    val query: LiveData<String> get() = _query

    fun updateQuery(newQuery: String) {
        _query.value = newQuery  // setValue() — di thread utama
    }

    fun updateFromNetwork(result: String) {
        _query.postValue(result)  // postValue() — dari thread mana pun
    }
}

setValue() harus dipanggil hanya dari thread utama (main thread) — segera memberitahu pengamat. postValue() aman dipanggil dari thread latar: menempatkan nilai dalam antrian thread utama dan memberitahu pengamat secara asinkron. Penting: jika postValue() dipanggil dua kali berturut-turut sebelum pemrosesan yang pertama, nilai perantara mungkin hilang — pengamat hanya akan menerima yang terakhir. Untuk mentransmisikan semua keadaan perantara (misalnya, kemajuan pemuatan) gunakan setValue() di thread utama.

Transformasi LiveData: map, switchMap, MediatorLiveData

Transformations.map() — transformasi fungsional nilai satu LiveData ke tipe lain tanpa menulis Observer. Misalnya, dari LiveData<User> mendapatkan LiveData<String> dengan nama pengguna. Transformasi bersifat malas: transformasi hanya dilakukan ketika ada Observer aktif di LiveData target.

kotlin
val userLiveData: LiveData<User> = ...
val userName: LiveData<String> = Transformations.map(userLiveData) { user ->
    "${user.firstName} ${user.lastName}"
}

val userIdLiveData: LiveData<String> = ...
val userDetails: LiveData<UserDetails> = Transformations.switchMap(userIdLiveData) { id ->
    repository.getUserDetails(id)
}

// MediatorLiveData — menggabungkan dua sumber
val mediator = MediatorLiveData<CombinedState>()
mediator.addSource(priceLiveData) { price ->
    mediator.value = CombinedState(price, countLiveData.value)
}
mediator.addSource(countLiveData) { count ->
    mediator.value = CombinedState(priceLiveData.value, count)
}

Transformations.switchMap() — analog flatMap dari dunia aliran reaktif: saat LiveData masukan berubah, ia beralih ke instance baru LiveData keluaran. MediatorLiveData — alat canggih untuk menggabungkan beberapa sumber LiveData dengan kemampuan mengelola prioritas pembaruan. Menurut Developer Survey (2024), MediatorLiveData digunakan di 35% proyek yang memerlukan agregasi data dari berbagai sumber — misalnya, menggabungkan data formulir UI dan respons server.

LiveData dengan coroutine: liveData builder

liveData { } — coroutine builder (muncul di lifecycle-livedata-ktx 2.2.0) yang memungkinkan komputasi asinkron nilai LiveData di dalam coroutine. Di dalam blok liveData { } tersedia konteks suspend, serta fungsi emit() untuk mempublikasikan nilai. Semua coroutine yang dijalankan di dalam builder secara otomatis dibatalkan saat semua pengamat tidak aktif.

kotlin
val userLiveData: LiveData<User> = liveData {
    // Dieksekusi di Dispatchers.IO secara default
    val user = userRepository.fetchUser(userId)
    // Keluarkan hasil — otomatis di thread utama
    emit(user)
}

val progressLiveData: LiveData<Int> = liveData {
    for (i in 0..100) {
        emit(i)
        delay(50)
    }
}

liveData builder mendukung emitSource() — emisi LiveData lain sebagai sumber (analog switchMap di dalam coroutine). Timeout: jika tidak ada Observer yang aktif selama 5 detik (standar), coroutine dibatalkan. Saat aktivasi ulang, liveData { } dieksekusi dari awal. Menurut Google (Android Dev Summit 2024), liveData builder mengurangi 40% kode boilerplate dibandingkan dengan manajemen manual ViewModel + LiveData.

Contoh kode: LiveData di Kotlin

Contoh 1: ViewModel dengan LiveData untuk layar login

Layar login klasik dengan bidang email dan kata sandi, validasi dan status pemuatan. ViewModel mengelola tiga LiveData: email, password dan loginResult.

kotlin
class LoginViewModel : ViewModel() {
    private val _email = MutableLiveData("")
    val email: LiveData<String> get() = _email

    private val _password = MutableLiveData("")
    val password: LiveData<String> get() = _password

    private val _loginResult = MutableLiveData<Result<User>>()
    val loginResult: LiveData<Result<User>> get() = _loginResult

    fun onEmailChanged(text: String) {
        _email.value = text
    }

    fun onPasswordChanged(text: String) {
        _password.value = text
    }

    fun login() {
        if (_email.value.isNullOrBlank() || _password.value.isNullOrBlank()) {
            _loginResult.value = Result.failure(IllegalArgumentException("Isi semua bidang"))
            return
        }
        viewModelScope.launch {
            try {
                val user = authRepository.login(_email.value!!, _password.value!!)
                _loginResult.value = Result.success(user)
            } catch (e: Exception) {
                _loginResult.value = Result.failure(e)
            }
        }
    }
}

Contoh 2: LiveData dengan Room dan coroutine

Room mendukung LiveData sebagai tipe kembalian kueri DAO: setiap kali tabel berubah, LiveData secara otomatis memberi tahu pengamat, yang ideal untuk UI reaktif.

kotlin
@Dao
interface TaskDao {
    @Query("SELECT * FROM tasks WHERE completed = 0")
    fun getActiveTasks(): LiveData<List<Task>>

    @Insert
    suspend fun insertTask(task: Task)
}

// Di ViewModel:
class TaskViewModel(application: Application) : AndroidViewModel(application) {
    private val dao = AppDatabase.getDatabase(application).taskDao()
    val activeTasks: LiveData<List<Task>> = dao.getActiveTasks()
}

Room menghasilkan kode yang melacak perubahan di tabel tasks dan secara otomatis memperbarui LiveData pada setiap INSERT, UPDATE atau DELETE. Ini bekerja tanpa kode tambahan — hanya anotasi @Query dengan tipe kembalian LiveData. Di IT Sectr kami menggunakan Room + LiveData sebagai tumpukan standar untuk caching data lokal di proyek Android sejak 2019.

Pertanyaan yang Sering Diajukan

Apa perbedaan antara LiveData dan StateFlow?

LiveData — wadah yang dapat diamati dengan dukungan Lifecycle bawaan: Observer secara otomatis aktif/nonaktif. StateFlow — aliran reaktif dari Kotlin Coroutines (Kotlinx Coroutines 1.3.7+), tidak terikat ke Lifecycle, tetapi mendukungnya melalui stateIn(WhileSubscribed). StateFlow memerlukan manajemen siklus hidup eksplisit di View, tetapi memberikan akses ke coroutine, operator Flow dan multiplatform. Google merekomendasikan StateFlow untuk proyek baru di Kotlin, LiveData — untuk kode Java atau saat diperlukan kompatibilitas dengan pustaka lama.

Bagaimana cara mengonversi LiveData ke StateFlow?

Gunakan fungsi ekstensi liveData.asFlow() dari pustaka lifecycle-livedata-ktx. Ini membuat Flow yang mengeluarkan nilai LiveData saat ini setiap kali berubah. Kemudian konversikan ke StateFlow melalui .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), initialValue). Konversi terbalik — stateFlow.asLiveData(). Konversi timbal balik memungkinkan penggunaan keunggulan kedua pustaka dalam satu proyek.

Kapan LiveData kehilangan data saat postValue?

postValue() menggunakan AtomicReference untuk menyimpan nilai yang ditunda. Jika postValue() dipanggil dua kali sebelum diproses oleh thread utama, nilai pertama akan ditimpa oleh yang kedua — Observable hanya menerima yang terakhir. Ini karena LiveData tidak memiliki antrian internal: hanya menyimpan satu nilai tertunda. Untuk mentransmisikan setiap titik perantara (1%, 2%, … 100%) gunakan setValue() di thread utama atau ConflatedFlow dari kotlinx-coroutines.

Bisakah LiveData digunakan tanpa LifecycleOwner?

Ya, LiveData dapat diamati melalui observeForever(), dengan mengirimkan Observer tanpa LifecycleOwner. Namun dalam kasus ini, penghentian langganan harus eksplisit melalui removeObserver() — penghentian otomatis tidak berfungsi. observeForever() diterapkan di service, ContentProvider atau ViewModel di mana LifecycleOwner tidak tersedia. Menurut rekomendasi Google, hindari observeForever() di Activity/Fragment — gunakan observe() dengan LifecycleOwner.

Apa itu LiveData versi 1.0 (selalu terkini)?

Fitur perilaku: ketika LiveData menerima Observer aktif baru, ia segera menerima nilai terakhir (jika diatur). Versi lama LiveData (sebelum lifecycle 2.5.0) mengirimkan nilai bahkan kepada pelanggan tidak aktif saat beralih ke keadaan aktif — ini telah diperbaiki. Di versi saat ini, LiveData menerima nilai terakhir saat transisi DARI tidak aktif KE aktif, yang menyederhanakan inisialisasi layar.

Kesimpulan

  • LiveData — wadah data yang dapat diamati dengan tautan otomatis ke Lifecycle, menghilangkan kebocoran memori dan crash akibat referensi usang.
  • MutableLiveData dengan setValue() (thread utama) dan postValue() (thread latar) — API utama untuk mengubah data.
  • Transformasi map(), switchMap() dan MediatorLiveData — rantai fungsional tanpa kode boilerplate.
  • liveData builder liveData { } — pendekatan coroutine untuk membuat LiveData asinkron dengan pembatalan coroutine otomatis.
  • Room + LiveData — kombinasi siap pakai untuk caching lokal tanpa kode tambahan di DAO.
  • LiveData digunakan di 74% proyek Jetpack dan tetap menjadi standar untuk kode Java dan arsitektur legacy.
  • Untuk proyek Kotlin baru, Google merekomendasikan StateFlow, tetapi LiveData tetap menjadi solusi kompatibel untuk tumpukan hibrida.

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