Jetpack Compose with Kotlin Flow: The Delegation Advantage!
In Kotlin the by
keyword is used for property delegation, which automates the getter & setter functions for a property. When you use by
tied to Compose’s collectAsState()
, the delegate allows the UI to observe state changes & update without needing to manually manage the value
property of the state. This makes code more dev friendly (readable) and idiomatic 👍🏾
// composable
val enabled by viewModel.enableRadioButtons.collectAsState()
// viewModel
private val _enable = MutableStateFlow(true)
val enableRadioButtons: StateFlow<Boolean> = _enable.asStateFlow()
fun enableRadioButtons(isEnabled: Boolean) {
flow<Boolean> {
_enableRadioButtons.emit(isEnabled)
}.catch {
_enableRadioButtons.emit(true)
}.launchIn(viewModelScope)
}
How does enabled
talk to the Composable radio buttons?
IconToggleButton(
checked = selectedAnswer.value == answer,
enabled = enabled,
onCheckedChange = {
viewModel.enableRadioButtons(false)
selectedAnswer.value = answer
},
modifier = Modifier
.size(dimensionResource(R.dimen.dimen_xxxlarge_26))
.padding(end = dimensionResource(R.dimen.dimen_medium_x))
) {
TriviaRadioButton(painter, color)
}
// Some context, when you select a radio button you choose and answer
// and can not choose again if wrong, so disable buttons reactively.
The line val enabled by viewModel.enableRadioButtons.collectAsState()
is used to observe changes from the viewModel
and update the enabled
state of the IconToggleButton
in real-time using Flows.
This ensures that the IconToggleButton
reflects the current state of interactivity as dictated by the viewModel
, allowing for a responsive & dynamic user experience.
— Assignment vs. Delegation —
// assigning enabled to state
val enabled = viewModel.enableRadioButton.collectAsState()
On the other hand, assigning the value directly without delegation for exampleval enabled = viewModel.enableRadioButtons.collectAsState()
, you’re not observing the changes of the Flow
. Instead, you’re assigning the State
object returned by collectAsState()
to enabled
, which won’t automatically update the Composable when the Flow
emits new values.
In Jetpack Compose, developers have the option to choose between direct assignment or utilizing the property delegation sugar. Ultimately it comes down to promoting clean architecture that is reactive, efficient and idiomatic:)
Try the trivia feature out in Jetpack Compose on Google Play 🥳🚀 https://play.google.com/store/apps/details?id=com.brickyard.nhl
Best,
RC