具有多个不同类型来源的LiveData

时间:2019-04-10 03:57:25

标签: android kotlin google-cloud-firestore android-livedata mutablelivedata

我目前有一个项目,其中包含MyItem列表,并且使用Firebase / LiveData。它分为几组,每个组都有项目。

如果发生以下任何情况,我希望能够更新此列表:

  1. 一项已更新(通过Firebase在后端)
  2. 更改过滤器(在Firebase上为每个用户创建一个单独的表)
  3. 一个项目被添加了书签(在Firebase上为每个用户一个单独的表)

要获取目录列表,我有一个类似这样的函数可返回LiveData,该LiveData将在项目更新(#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
}

在ViewModel中,我具有处理这种情况的逻辑。

viewmodel

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
        }
    }

逻辑很复杂,很难遵循。有没有更好的方法来构造它来处理多个不同的更改?存储用户当前过滤器的最佳方法是什么?

谢谢。

2 个答案:

答案 0 :(得分:1)

我不知道我是否正确回答了您的问题,但是如果您的视图使用一个列表(例如compile之类的东西),并且该列表在多种情况下已更新或更改,则您必须工作与MyItemList

我的意思是,您必须有三个MediatorLiveData,每个负责一个情况,一个MediatorLiveData通知每个人是否已更改。

请参见下文

数据库

LiveData

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) } 中,您有一个viewModel会在这MediatorLiveData上观察,直到有任何数据更改通知视图为止。

viewModel

liveData

答案 1 :(得分:1)

您对contents的实现包括对外部变量的多个引用,这使得难以跟踪和跟踪状态。我只是将引用尽可能地保留在本地,并信任switchMap(liveData)做适当的工作。以下代码应该与您的代码相同:

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
}

关于getList(id),您可能还希望正确处理exception