android - StateFlow 收集不会针对列表类型触发

标签 android android-viewmodel kotlin-stateflow

@HiltViewModel
class HistoryViewModel @Inject constructor(private val firebaseRepository: FirebaseRepository) :
    ViewModel() {

    private val translateList: MutableList<Translate> = mutableListOf()

    private val _translateListState: MutableStateFlow<List<Translate>> =
        MutableStateFlow(translateList)

    val translateListState = _translateListState.asStateFlow()

    init {
        listenToSnapshotData()
    }

    private suspend fun addItemToList(translate: Translate) {
        Log.d("customTag", "item added adapter $translate")
        translateList.add(translate)
        _translateListState.emit(translateList)
    }

    private suspend fun removeItemFromList(translate: Translate) {
        Log.d("customTag", "item removed adapter $translate")
        val indexOfItem = translateList.indexOfFirst {
            it.id == translate.id
        }
        if (indexOfItem != -1) {
            translateList.removeAt(indexOfItem)
            _translateListState.emit(translateList)
        }
    }

    private suspend fun updateItemFromList(translate: Translate) {
        Log.d("customTag", "item modified adapter $translate")
        val indexOfItem = translateList.indexOfFirst {
            it.id == translate.id
        }
        if (indexOfItem != -1) {
            translateList[indexOfItem] = translate
            _translateListState.emit(translateList)
        }
    }

    private fun listenToSnapshotData() {
        viewModelScope.launch {
            firebaseRepository.translateListSnapshotListener().collect { querySnapshot ->
                querySnapshot?.let {
                    for (document in it.documentChanges) {
                        val translateData = document.document.toObject(Translate::class.java)
                        when (document.type) {
                            DocumentChange.Type.ADDED -> {
                                addItemToList(translate = translateData)
                            }
                            DocumentChange.Type.MODIFIED
                            -> {
                                updateItemFromList(translate = translateData)
                            }
                            DocumentChange.Type.REMOVED
                            -> {
                                removeItemFromList(translate = translateData)
                            }
                        }
                    }
                }
            }
        }
    }
}

这里的数据在 listenToSnapshotData 函数的 querySnapshot 中正确出现。并发布它正确调用相应的函数来更新列表。
但在此行之后 _translateListState.emit(translateList) 流程不会转到相应的 collectLatest

private fun observeSnapShotResponse() {
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                historyViewModel.translateListState.collectLatest {
                    Log.d("customTag", "calling submitList from fragment")
                    translateListAdapter.submitList(it)
                }
            }
        }
    }

从 fragment 调用submitList在开始时被调用一次,但是当在 ListView 模型中修改数据时,回调不会到达collectLatest

最佳答案

这来自 StateFlow 文档:

Values in state flow are conflated using Any.equals comparison in a similar way to distinctUntilChanged operator. It is used to conflate incoming updates to value in MutableStateFlow and to suppress emission of the values to collectors when new value is equal to the previously emitted one.

您试图始终发出相同的 List 实例,但由于文档中的内容,这没有任何效果。您每次都必须创建列表的新实例。

关于android - StateFlow 收集不会针对列表类型触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73597141/

相关文章:

Android - 如何从 kotlin 流中读取值?

android - 如何在视频系统中捕获和编码音频_Android

android 应用内导入 csv

java - 安卓xmpp库

android - 如何从我的适配器 onClick 打开一个 fragment

java - 进行单元测试时无法将Value 设置为 MutableLiveData - 抛出 java.lang.reflect.InvocableTargetException

android - jetpack compose 中未显示流量数据

android - 多次调用 livedata observe 的 onChanged 方法

android - 如何对返回 livedata 的函数进行单元测试

kotlin - 如何在kotlin中打印流的大小