I currently have a project that contains a list of MyItem
, and using Firebase/LiveData. It's structured into groups, and each group has items.
I want to be able to update this list if any of the following happen:
To get the list of contents, I have a function like this to return LiveData that will update whenever an item is updated (#1).
getList(id: String): LiveData<List<MyItem>> {
val data = MutableLiveData<List<MyItem>>()
firestore
.collection("groups")
.document(id)
.collection("items")
.addSnapshotListener { snapshot, exception ->
val items = snapshot?.toObjects(MyItem::class.java) ?: emptyList()
// filter items
data.postValue(items)
}
return data
}
And within my ViewModel, I have logic for handling that case.
private val result = MediatorLiveData<Resource<List<MyItem>>>()
private var source: LiveData<List<MyItem>>? = null
val contents: LiveData<Resource<List<MyItem>>>
get() {
val group = database.group
// if the selected group is changed.
return Transformations.switchMap(group) { id ->
// showing loading indicator
result.value = Resource.loading(null)
if (id != null) {
// only 1 source for the current group
source?.let {
result.removeSource(it)
}
source = database.getList(id).also {
result.addSource(it) {
result.value = Resource.success(it)
}
}
// how to add in source of filter changes?
} else {
result.value = Resource.init(null)
}
return@switchMap result
}
}
The logic is pretty complex, and hard to follow. Is there a better way to structure this to handle multiple different changes? What's the best way to store the user's current filters?
Thanks.
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:
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.
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)
}
});
}