Sepertinya MutableLiveData
berbeda dari LiveData
hanya dengan membuat setValue()
dan postValue()
metode publik, sedangkan di dalamnya LiveData
dilindungi.
Apa alasan untuk membuat kelas terpisah untuk perubahan ini dan tidak hanya mendefinisikan metode tersebut sebagai publik LiveData
itu sendiri?
Secara umum, apakah bentuk pewarisan semacam itu (meningkatkan visibilitas metode tertentu menjadi satu-satunya perubahan) merupakan praktik yang terkenal dan beberapa skenario apa yang mungkin berguna (dengan asumsi kita memiliki akses ke semua kode)?
android
oop
android-architecture-components
android-livedata
Alexander Kulyakhtin
sumber
sumber
LiveData
tidak dapat diubah, karena klien tidak dapat mengubah status internal, oleh karena itu aman utasJawaban:
Di LiveData - Dokumentasi Pengembang Android , Anda dapat melihat bahwa untuk
LiveData
,setValue()
&postValue()
metode tidak bersifat publik.Padahal, di MutableLiveData - Dokumentasi Pengembang Android , Anda dapat melihat bahwa,
MutableLiveData
meluasLiveData
secara internal dan juga dua metode keajaibanLiveData
yang umum tersedia di ini dan merekasetValue()
&postValue()
.setValue()
: mengatur nilai dan mengirimkan nilai ke semua pengamat aktif, harus dipanggil dari utas utama .postValue()
: memposting tugas ke utas utama untuk mengganti nilai yang ditetapkansetValue()
, harus dipanggil dari utas latar belakang .Jadi, tidak
LiveData
bisa diubah .MutableLiveData
adalahLiveData
yang bisa berubah & aman utas .sumber
Ini adalah keseluruhan
MutableLiveData.java
file:package androidx.lifecycle; /** * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method. * * @param <T> The type of data hold by this instance */ @SuppressWarnings("WeakerAccess") public class MutableLiveData<T> extends LiveData<T> { @Override public void postValue(T value) { super.postValue(value); } @Override public void setValue(T value) { super.setValue(value); } }
Jadi ya, perbedaan hanya datang dari pembuatan
postValue
dansetValue
publik.Satu kasus penggunaan yang bisa saya ingat adalah untuk enkapsulasi menggunakan Backing Property di Kotlin. Anda dapat mengekspos
LiveData
Fragmen / Aktivitas (Pengontrol UI) meskipun Anda dapat memilikiMutableLiveData
manipulasi diViewModel
kelas Anda .class TempViewModel : ViewModel() { ... private val _count = MutableLiveData<Int>() val count: LiveData<Int> get() = _count public fun incrementCount() = _count.value?.plus(1) ... }
Dengan cara ini Pengontrol UI Anda hanya dapat mengamati nilai tanpa dapat mengeditnya. Jelas, Pengontrol UI Anda dapat mengedit nilai menggunakan metode publik
TempViewModel
sejenisincrementCount()
.Catatan : Untuk memperjelas kebingungan yang bisa berubah / tidak berubah -
data class User(var name: String, var age: Int) class DemoLiveData: LiveData<User>() var demoLiveData: LiveData<User>? = DemoLiveData() fun main() { demoLiveData?.value = User("Name", 23) // ERROR demoLiveData?.value?.name = "Name" // NO ERROR demoLiveData?.value?.age = 23 // NO ERROR }
sumber
_score
?MutableLiveData diturunkan dari LiveData. Metode yang dilindungi LiveData hanya dapat ditangani oleh diri sendiri atau subkelas. Jadi dalam hal ini MutableLiveData sebagai sub kelas LiveData dapat mengakses metode yang dilindungi ini.
Apa yang ingin Anda lakukan adalah mengamati pada sebuah contoh dan melihat apakah ada perubahan. Tetapi pada saat yang sama Anda tidak ingin ada "orang luar" yang mengubah contoh yang Anda amati. Dalam arti tertentu ini menciptakan masalah, karena Anda ingin memiliki objek yang dan dapat diubah, untuk memperbarui status baru, dan tidak dapat diubah, untuk memastikan tidak ada orang yang tidak dapat memperbarui contoh ini. Kedua fitur ini saling bertentangan tetapi dapat diselesaikan dengan membuat lapisan tambahan.
Jadi yang Anda lakukan adalah memperluas kelas Anda, LiveData, dengan kelas yang dapat mengakses metodenya. Sub lapisan, dalam hal ini MutableLiveData, dapat mengakses metode yang dilindungi dari induknya (/ super).
Sekarang Anda mulai membuat instance, dan membuat instance pengamat Anda dari MutableLiveData. Pada saat yang sama Anda membuat instance LiveData yang merujuk ke instance yang sama ini. Karena MutableLiveData memperluas LiveData, setiap instance MutableLiveData adalah objek LiveData dan oleh karena itu dapat direferensikan oleh variabel LiveData.
Sekarang triknya hampir selesai. Anda hanya mengekspos instance LiveData, tidak ada yang dapat menggunakan metode terlindungnya, juga tidak dapat mentransmisikannya ke supernya (mungkin pada waktu kompilasi, tetapi tidak akan berjalan: RunTime error). Dan Anda membuat instance subkelas yang sebenarnya tetap pribadi, jadi itu hanya dapat diubah oleh mereka yang memiliki instance, menggunakan metode instance.
//create instance of the sub class and keep this private private val _name: MutableLiveData<String> = MutableLiveData<String>() //create an instance of the super class referring to the same instance val name: LiveData<String> = _name
//assign observer to the super class, being unable to change it name.value.observe(.....)
Sekarang kelas super memberi tahu jika ada perubahan yang diterapkan.
//change the instance by using the sub class _name.postValue(...) //or _name.setValue(...)
Ya, ini cukup terkenal dan ini dijelaskan di atas adalah skenario umum. Hapus pola pengamat, dan buat dalam bentuk set / get akan mendapatkan banyak keuntungan darinya. Tergantung dari mana Anda menerapkannya, tidak ada aturan emas pada akhirnya.
sumber