I have a StateFlow screen state in the ViewModel which I'm trying to propagate to a Composable screen through a Fragment. In some cases, the screen is not being recomposed even when the state changes.
I know for sure that the value of the screen state is changing because I'm able to collect it in the fragment using viewModel.screenState.collectLatest.
ViewModel.kt
class MyViewModel: ViewModel() {
private val someData1 = MutableStateFlow("initialData1")
private val someData2 = MutableStateFlow("initialData2")
val screenState: StateFlow<ScreenState> = combine(someData1, someData2) { data1, data2 ->
// ScreenState is a data class
ScreenState(data1, data2)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = ScreenState("initialData1", "initialData2"),
)
}
MyFragment.kt
class MyFragment: Fragment() {
private val viewModel: MyViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = ComposeView(inflater.context).apply {
lifecycleScope.launch {
viewModel.screenState.collectLatest {
Log.d(TAG, "new state is always collected here successfully")
}
}
setContent {
val screenState by viewModel.screenState.collectAsState()
// SOMETIMES NOT RECOMPOSING!!!
MyScreen(
screenState = screenState,
)
}
}
}
MyScreen.kt
@Composable
fun MyScreen(
screenState: ScreenState,
) {
Log.d(TAG, "screen not recomposing on state change") // this line not called!
}
Replacing collectAsState with collectAsStateWithLifecycle didn't help.
Using androidx.compose:compose-bom:2023.06.01.
Here, You are using fragment that will not recompose every time, for that you have to use @Composable (it will recompose every time it notices any changes in data)
I think use of fragments in compose is bad habit. You should use compose navigation graph with different composable screens.
you can refer this link for compose navigation https://medium.com/google-developer-experts/navigating-in-jetpack-compose-78c78d365c6a