I am trying to make a simple app that uses firestore, that just insert the token of devices and fetch the names corresponding to that token. When I tried to fetch "name" value , the flow in my helper class getting the correct value, but viewModel is not getting that value .
I think I got 2 observation from the log->
1. By seeing the log , first
2024-10-05 09:32:29.658 29752-29808 FirestoreHelperForToken com.example.fcmpractice D Setting up addSnapshotListener
first my class is created. then My viewModel tried to access the value , therefore this log is coming
"2024-10-05 09:32:30.350 29752-29752 ChatViewModel com.example.fcmpractice D List is null "
then fetchAllName of variable is accessing it
"2024-10-05 09:32:30.826 29752-29752 FirestoreHelperForToken com.example.fcmpractice D Snapshot size: 10
2024-10-05 09:32:30.833 29752-29752 FirestoreHelperForToken com.example.fcmpractice D Names list: [mona, abhijit, mahesh, ritu, jodha, madhav, babu, raghav, mamu, nammy] "
maybe that's why my viewModel is not taking getting the value.
2. In my viewModel , this code piece
viewModelScope.launch {
firestoreHelperForToken.fetchAllNames.collect { names ->
_getAllNames.value = names
Log.d("ChatViewModel", "Fetched names from Firestore: $names")
}
}
log inside collect function is not printing. I don't know why. Please help me get your opinion and help.
These are my code files, I tried using the log in every step but cannot solve the problem.
Helper class(important part)
class FirestoreHelperForToken { val scope = CoroutineScope(Dispatchers.IO) private val TAG = "FirestoreHelperForToken" private val _db = Firebase.firestore val fetchAllNames: Flow<List<String>> = channelFlow { trySend(emptyList()) Log.d(TAG, "Setting up addSnapshotListener") _db.collection("tokens") .addSnapshotListener { snapshot, e -> if (e != null) { Log.w(TAG, "Listen failed with error: $e") return@addSnapshotListener } if (snapshot == null || snapshot.isEmpty) { Log.d(TAG, "Snapshot is null or empty.") trySend(emptyList()) // Emit empty list if no documents are found return@addSnapshotListener } val namesList = mutableListOf<String>() Log.d(TAG, "Snapshot size: ${snapshot.size()}") for (document in snapshot.documents) { val name = document.getString("name") name?.let { namesList.add(it) } } try { Log.d(TAG, "Names list: $namesList") trySend(namesList) // Emit the list of names } catch (sendError: Exception) { Log.e(TAG, "Error while sending names list: ${sendError.message}") } } }.flowOn(Dispatchers.IO) } data class TokenData( val name: String, val token: String )ViewModel(important part regarding the question)
class ChatViewModel ( private val chatRepository: ChatRepository, application: Application ) : AndroidViewModel(application) { val firestoreHelperForToken = FirestoreHelperForToken() private val _getAllNames = MutableLiveData<List<String>>() val getAllNames : LiveData<List<String>> get() = _getAllNames init { //subscribe to a topic to broadcast the message viewModelScope.launch { firestoreHelperForToken.fetchAllNames.collect { namesList -> _getAllNames.value = namesList // Log inside the collect block to ensure that the data is fetched Log.d("ChatViewModel", "List from Firestore: $namesList") // Small delay to ensure data sync if needed delay(100) // Check if list is not null or empty and log it if (!namesList.isNullOrEmpty()) { Log.d("ChatViewModel", "Valid list received: $namesList") } else { Log.d("ChatViewModel", "Empty list received.") } } // Log outside of the collect block after it finishes fetching Log.d("ChatViewModel", "List outside the collect block: ${getAllNames.value}") } }AppNavigation
@Composable fun AppNavigation(viewModel: ChatViewModel,context: Context){ val navController = rememberNavController() val state = viewModel.state NavHost(navController = navController, startDestination = "JoinConversation") { composable(route = "JoinConversation"){ EnteringTokenScreen( onJoinConversationClicked = { navController.navigate("ChatListScreen") }, name = state.nameText, onNameChange = viewModel::onNameChange, onSaveTokenClicked = { viewModel.insertToken(it,onSameName = { Toast.makeText(context,"Name already exists",Toast.LENGTH_SHORT).show() }) } ) } composable(route = "ChatListScreen"){ val nameList = viewModel.getAllNames.observeAsState(emptyList()) ChatListScreen(nameList.value) } } }ChatListScreen
@Composable fun ChatListScreen(nameList : List<String>){ LazyColumn ( modifier = Modifier .fillMaxSize() .padding(16.dp) ){ items(nameList){ name-> Text(text = name) } } }Logs I am getting are as follows
2024-10-05 10:24:09.915 30753-30779 FirestoreHelperForToken com.example.fcmpractice D Setting up addSnapshotListener 2024-10-05 10:24:10.645 30753-30753 ChatViewModel com.example.fcmpractice D List from Firestore: [] 2024-10-05 10:24:10.650 30753-30753 FirestoreHelperForToken com.example.fcmpractice D Snapshot size: 12 2024-10-05 10:24:10.670 30753-30753 FirestoreHelperForToken com.example.fcmpractice D Names list: [mona, abhijit, mahesh, ritu, jodha, biru, madhav, babu, sujal, raghav, mamu, nammy] 2024-10-05 10:24:10.751 30753-30753 ChatViewModel com.example.fcmpractice D Empty list received. 2024-10-05 10:24:10.758 30753-30753 ChatViewModel com.example.fcmpractice D List outside the collect block: []