Advanced State Management in Compose
MVI Pattern
sealed class UserIntent {
object Load : UserIntent()
data class UpdateName(val name: String) : UserIntent()
}
data class UserState(
val name: String = "",
val isLoading: Boolean = false,
val error: String? = null
)
fun reducer(state: UserState, intent: UserIntent): UserState = when (intent) {
UserIntent.Load -> state.copy(isLoading = true)
is UserIntent.UpdateName -> state.copy(name = intent.name)
}
Reducer Pure Function
@Composable
fun UserScreen() {
var state by remember { mutableStateOf(UserState()) }
fun dispatch(intent: UserIntent) {
state = reducer(state, intent)
}
dispatch(UserIntent.Load)
}
Channel for One-Shot UiEffect
val effectChannel = Channel<UiEffect>(Channel.BUFFERED)
LaunchedEffect(Unit) {
for (effect in effectChannel) {
when (effect) {
is UiEffect.ShowToast -> showToast(effect.message)
is UiEffect.Navigate -> navigate(effect.route)
}
}
}
State Splitting for Recomposition Optimization
@Composable
fun OptimizedScreen() {
val listState by viewModel.listState.collectAsState()
val headerState by viewModel.headerState.collectAsState()
Column {
// HeaderState recomposes only when headerState changes
Header(headerState)
// ListState recomposes independently
List(listState.items)
}
}
8 Android app templates on Gumroad
Top comments (0)