LiveData with multiple sources of different types
I don't know am I get your question correctly or not, but if you have a view that work with one list (something like MyItemList
) and this list updated or changed by several situations, you must work with MediatorLiveData
.
I mean you must have three LiveData
that each one responsible for a situation and one MediatorLiveData that notified if each one of them has changed.
see below:
database
fun getListFromServer(id: String): LiveData<List<MyItem>> {
val dataFromServer = MutableLiveData<List<MyItem>>()
firestore
.collection("groups")
.document(id)
.collection("items")
.addSnapshotListener { snapshot, exception ->
val items = snapshot?.toObjects(MyItem::class.java) ?: emptyList()
dataFromServer.postValue(items)
}
return dataFromServer
}
fun getFilteredData(id: String): LiveData<FilterData> {
return DAO.user.getFilteredData(id)
}
fun getBookmarkedList(id: String): LiveData<BookmarkData> {
return DAO.user.getBookmarkedData(id)
}
And in the viewModel
you have one MediatorLiveData
that observe on these liveData
s till if any data has changed notify view.
viewModel
private val result = MediatorLiveData<<List<MyItem>>()
fun observeOnData(id: String, owner: LifeCycleOwner, observer: Observer<List<MyItem>>) {
result.observe(owner, observer);
result.addSource(Database.getListFromServer(id), MyItemList -> {
if(MyItemList != null)
result.setValue(MyItemList)
});
result.addSource(Database.getFilteredData(id), filterData -> {
if(filterData != null) {
val myItemList = result.getValue()
if (myItemList == null) return
//here add logic for update myItemList depend On filterData
result.setValue(myItemList)
}
});
result.addSource(Database.getBookmarkedList(id), bookmarkData -> {
if(MyItemList != null) {
val myItemList = result.getValue()
if (myItemList == null) return
//here add logic for update myItemList depend On bookmarkData
result.setValue(myItemList)
}
});
}
Your implementation of contents
includes several references to outer variables, which makes it hard to follow and keep track of the state. I'd just keep the references as local as possible and trust switchMap(liveData)
to do a proper job. The following code should be doing just the same as yours:
val contents = Transformations.switchMap(database.group) { id ->
val data = MediatorLiveData<Resource<List<MyItem>>()
if (id == null) {
data.value = Resource.init(null)
} else {
data.value = Resource.loading(null)
data.addSource(database.getList(id)) {
data.value = Resource.success(it)
}
}
return liveData
}
In regards of getList(id)
you might also want to handle the exception
properly.