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

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

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

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

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

为了获取内容列表,我有一个类似这样的函数来返回 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 中,我有处理这种情况的逻辑。

View 模型

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

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

谢谢。

最佳答案

我不知道我是否正确地回答了你的问题,但是如果你有一个与一个列表一起工作的 View (类似于 MyItemList)并且这个列表在几种情况下更新或更改,您必须使用 MediatorLiveData

我的意思是你必须有三个 LiveData,每个负责一种情况,还有一个 MediatorLiveData,如果它们中的每一个都发生了变化,就会发出通知。

见下文:

数据库

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 观察这些 liveData,直到任何数据已更改通知 View 。

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

}

关于android - 具有多个不同类型来源的 LiveData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55604553/

相关文章:

android - WebRTC 的 Kurento-Group-Call 示例

android - 如何持续更新用户位置

concatenation - (数字+ “Is more than 5”)未运行 “Concatenation error”

kotlin - Aspectj 不适用于 kotlin

javascript - 从sql中提取十进制值

android - 圆形快速联系徽章

Kotlin - 如何对矩阵的每个元素应用模运算?

javascript - Firestore onSnapshot() 方法多次触发

javascript - 无法在复选框上输入 addEventListener?

firebase - Flutter:Java 使用或覆盖已弃用的 API