skip to Main Content

Expected Behavior: When the button is clicked, it should immediately update the text and color to reflect the new reward value.

Actual Behavior: When the button is clicked, it calls the functions to update the data and save it to Firestore. However, the UI is not updating until the screen is reloaded.

Tried Things: I’ve switched from LiveData to StateFlow but that did not solve it.

Repository:

var currentUser = MutableStateFlow<User?>(null)
        private set
fun updateCurrentUserFirestore() {
        val updatedUser = hashMapOf(
            "skipCoins" to currentUser.value?.skipCoins,
            "tasksDone" to currentUser.value?.tasksDone,
            "tasksSkipped" to currentUser.value?.tasksSkipped,
            "gamesWon" to currentUser.value?.gamesWon,
            "gamesLost" to currentUser.value?.gamesLost,
            "reward" to currentUser.value?.reward
        )
        firestore.collection("user").document(currentUser.value?.userId.toString())
            .set(updatedUser)
            .addOnSuccessListener {
                Log.d(TAG, "updateCurrentUserFirebase:success")
            }
            .addOnFailureListener {
                Log.w(TAG, "updateCurrentUserFirebase:failure", it)
            }
    }

    fun changeRewardCurrentUser() {
        if (currentUser.value?.reward == "Joke") {
            currentUser.value.let {
                if (it != null) {
                    currentUser.value = User(
                        userId = it.userId,
                        skipCoins = it.skipCoins,
                        tasksDone = it.tasksDone,
                        tasksSkipped = it.tasksSkipped,
                        gamesWon = it.gamesWon,
                        gamesLost = it.gamesLost,
                        reward = if (it.reward == "Joke") "Bored" else "Joke"
                    )
                }
            }
        }
    }
fun updateCurrentUser(uid: String) {
        firestore.collection("user").document(uid)
            .get()
            .addOnSuccessListener { result ->
                currentUser.value = User(
                    userId = result.id,
                    skipCoins = result.data?.get("skipCoins").toString().toLong(),
                    tasksDone = result.data?.get("tasksDone").toString().toLong(),
                    tasksSkipped = result.data?.get("tasksSkipped").toString().toLong(),
                    gamesWon = result.data?.get("gamesWon").toString().toLong(),
                    gamesLost = result.data?.get("gamesLost").toString().toLong(),
                    reward = result.data?.get("reward").toString()
                )
                Log.d(TAG, "updateCurrentUserLocal:success")
            }
            .addOnFailureListener {
                Log.w(TAG, "updateCurrentUserLocal:failure", it)
            }
    }
ViewModel:

val currentUser: StateFlow<User?> = repository.currentUser
fun updateCurrentUserFirestore() {
        repository.updateCurrentUserFirestore()
    }

    fun changeRewardCurrentUser() {
        repository.changeRewardCurrentUser()
    }
Composable:

val user by viewModel.currentUser.collectAsState()
Button(
                        shape = ShapeDefaults.ExtraSmall,
                        onClick = {
                            viewModel.changeRewardCurrentUser()
                            viewModel.updateCurrentUserFirestore()
                        },
                        colors = ButtonDefaults.buttonColors(
                            containerColor = if (user?.reward == "Joke") Purple40 else Orange80,
                            contentColor = if (user?.reward == "Joke") Orange80 else Purple40
                        ),
                        modifier = Modifier.width(
                            calcDp(
                                percentage = 0.25f,
                                dimension = Dimension.Width
                            )
                        )
                    ) {
                        user?.let { Text(text = it.reward) }
                    }

2

Answers


  1. Chosen as BEST ANSWER

    I just fixed my problem yay, here the solution:

    Add this in graddle implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2")

    And use .collectAsStateWithLifecycle instead of .collectAsState in the Composable


  2. When you’re calling Query#get(), you’re only reading the data once. This means that after you get the data if something on the server is changed, you aren’t notified about that change. What you are looking for is to get real-time updates. This means that each time something on the server changes, you are notified in real-time.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search