我目前有一个包含MyItem个列表的项目,使用Firebase/LiveData.它被分成几个小组,每个小组都有项目.

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

  1. An item is updated (on the backend through Firebase)
  2. A filter is changed (a separate table on Firebase for each user)
  3. An item is bookmarked (a separate table on Firebase for each user)

To get the list of contents, I have a function like this to return LiveData that will update whenever an item is updated (#1).

database

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.

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

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?

谢谢.

推荐答案

我不知道我是否正确地理解了你的问题,但是如果你有一个视图可以处理一个列表(大约MyItemList个),并且这个列表在几个情况下更新或更改,那么你必须处理MediatorLiveData.

我的意思是,你必须有三个LiveData,每一个都要对一种情况负责,还有一个数据,如果每一个都发生了变化,就会通知你.

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

}

Kotlin相关问答推荐

只能在元素区域中点击的Jetpack Compose列

我可以检测一个函数是否在Kotlin中被递归调用(即,重入)吗?

Jetpack Compose Material3和Material2 Slider onValueChangeFinded()的行为不同

Kotlin stlib中是否有用于将列表<;对<;A,B&>;转换为对<;列表<;A&>,列表<;B&>;的函数

Kotlin Poet 的导入不明确

通过快捷键手动砍掉功能参数等

列表在 android WebView 中没有正确迭代

为什么会出现Kotlin.Unit错误以及如何修复它?

修改器的属性是什么,我需要更改以使角变圆且宽度更小?喷气背包组合

Kotlin 数据类中的大量参数

高效匹配两个 Flux

如何使用 Hilt 注入应用程序:ViewModel 中的上下文?

参考 Kotlin 中的 Java 接口静态字段

Kotlin 单元测试 - 如何模拟 Companion 对象的组件?

将 Android Studio 升级到 3.1.0 后的 Android Support 插件错误

使用 Kotlin 创建自定义 Dagger 2 范围

Kotlin:使用自定义设置器时没有lateinit的解决方法?

在android的默认浏览器 Select 列表中添加我的浏览器?

在Kotlin中将列表转换为对的惯用方法

如何在 Kotlin 中按字母顺序对字符串进行排序