0

Communicate from composable to fragment using viewmodel

I am having a Composable

@Composable
fun SimpleBottomButton(SCVM: StudioComposeViewModel) {
    Button(onClick = {
        SCVM.setbottomButtonClick(2)
    }) {
        Text(text = "Bottom Button")
    }
}

and a viewmodel

class ComposeViewModel(
    savedStateHandle: SavedStateHandle,
) : ViewModel() {
 private val _bottomButtonClick = MutableStateFlow(
        savedStateHandle["BottomButtonClick"] ?: 0
    )
    val bottomButtonClick
        get() =  _bottomButtonClick.asStateFlow()
    fun setbottomButtonClick(valuer: Int) {
        _bottomButtonClick.value = valuer
    }

}

in the fragment I want to get the data from viewmodel in a Fragment using this

 viewLifecycleOwner.lifecycleScope.launch {
            SCVM.bottomButtonClick.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED)
                .collect {
                    Log.e("bottomButtonClick",it.toString())

                    Toast.makeText(requireActivity(), it.toString(),Toast.LENGTH_SHORT).show()

                }
        }

However the data is not received

1234567
  • 2,226
  • 4
  • 24
  • 69

1 Answers1

0

I think you will receive the first click event as your state flow changes its value from 0 to 2. All the next events will not be emitted because StateFlow will not emit a new value if the new value is equal to its current value.

See

Values in state flow are conflated using Any.equals comparison in a similar way to distinctUntilChanged operator.

fshdn19
  • 374
  • 1
  • 8
  • but even the first click value of 2 is not received – 1234567 Mar 29 '23 at 06:28
  • I am trying to log the value in `fun setbottomButtonClick(valuer: Int)` and it is logged however it is not logged in fragment `viewLifecycleOwner.lifecycleScope.launch` – 1234567 Mar 29 '23 at 06:31
  • Yes, your callback will still get an invocation. It's just a function. The problem is your state flow will not update, Because the updated value is equal with it's current value. – fshdn19 Mar 29 '23 at 07:06
  • Can you log your current state-flow value in your `setbottomButtonClick` function? – fshdn19 Mar 29 '23 at 07:19
  • `Can you log your current state-flow value in your setbottomButtonClick function?` yes – 1234567 Mar 29 '23 at 10:09
  • Post the log please – fshdn19 Mar 29 '23 at 10:16
  • fun setBottomButtonClick(valuer: Int) { _bottomButtonClick.value = valuer Log.e("valuer",valuer.toString()) Log.e("valuer bottomButtonVisibility",bottomButtonClick.value.toString()) } this is the function and it displays 2023-03-29 12:03:32.263 30989-30989 valuer com.test.app E 2 2023-03-29 12:03:32.263 30989-30989 valuer bot...Visibility com.test.app E 2 – 1234567 Mar 29 '23 at 10:25
  • Come on, you should log the value before you set it. After that, it's always `2` so your log makes no sense – fshdn19 Mar 29 '23 at 10:31
  • will try as you sugest – 1234567 Mar 29 '23 at 10:31
  • this is the Log I get now 2023-03-29 16:04:48.577 29048-29048 before com.test.app E 0 2023-03-29 16:04:48.577 29048-29048 valuer com.test.app E 2 2023-03-29 16:04:48.578 29048-29048 valuer bot...Visibility com.test.app E 2 – 1234567 Mar 29 '23 at 10:36
  • I have tried your code and it works. Where did you write the collector – fshdn19 Mar 29 '23 at 11:51
  • Can i see your completely function where you register the collector – fshdn19 Mar 29 '23 at 11:59
  • So can you tell me the root cause? – fshdn19 Mar 30 '23 at 03:33
  • the problem is handling the click fun incrementCounter() { // Update state value based on some logic _counterState.value = _counterState.value + 1 } – 1234567 Mar 30 '23 at 09:56