StateFlow collect not firing for list type

Viewed 30
@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)
                            }
                        }
                    }
                }
            }
        }
    }
}

Here data comes properly in querySnapshot in listenToSnapshotData function. And post that it properly calls corresponding function to update the list.
But after this line _translateListState.emit(translateList) flow doesn't go to corresponding collectLatest

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

calling submitList from fragment is called once at the start, but as & when data is modified in list viewmodel, callback doesn't come to collectLatest

1 Answers

This is from StateFlow documentation:

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.

You are trying to emit the same instance of List all the time, which has no effect because of what is written in the docs. You will have to create new instance of the list every time.

Related