Hi John,
I have been experimenting with StateFlow and Compose in the last days, and it seems really amazing.
I was able to really move the whole model to the shared/multiplatform section, so that the platform-specific code is really just the UI.
If you use StateFlow, you can really stop using platform-specific structures such as LiveData.
You might want to have a look into that, as it greatly simplifies everything.
This is how StateFlow works with Compose:
class MainActivity : AppCompatActivity() {
val viewModel = ViewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyTextComponent(viewModel.state)
}
}
}
@Composable
@ExperimentalCoroutinesApi
fun MyTextComponent(stateFlow: StateFlow<DataModel>) {
val state by stateFlow.collectAsState()
Text(text = state.mytext)
}
One of the big architecture philosophy behind the StateFlow is essentially the MVI pattern.
You don't talk anymore in terms of dataActions, but in terms of userActions (also referred to as "Intents").
So, in the platform-specific section, you would not call functions as "fetchBikeShareInfo", but as "ClickOnButton", "ClickOnLink", etc.
On the platform-specific section, you don't deal with data at all, as the whole model is fully contained in the shared/multiplatform section. Your platform-specific user intents would just trigger a function that is defined inside the shared/multiplatform section, and all the data processing happens there.
class ViewModel {
private val webservicesAPI = WebservicesAPI()
private val _state = MutableStateFlow(DataModel())
val state: StateFlow<DataModel>
get() = _state
fun ClickOnButton(buttonType: String) {
launch {
val fetchedText = webservicesAPI.fetchText(buttonType)
_state.value = _state.value.copy(mytext = fetchedText)
}
}
}
data class DataModel(
val mytext : String = "initial text"
)