In MVI, when state changes, by default all UI elements observing that state will be recomposed. However, there are several ways to optimize this:
Use derivedStateOf for each list:
data class ViewState( val students: List, val teachers: List )
val studentsState = derivedStateOf { state.students } val teachersState = derivedStateOf { state.teachers }
LazyColumn { items(studentsState.value) { student -> // This will only recompose when students list changes } }
Split your state class and use multiple StateFlow:
class ViewModel { private val _studentsState = MutableStateFlow<List>(emptyList()) val studentsState = _studentsState.asStateFlow()
private val _teachersState = MutableStateFlow<List<Teacher>>(emptyList()) val teachersState = _teachersState.asStateFlow() }// In your UI LazyColumn { items(viewModel.studentsState.collectAsState().value) { student -> // Only recomposes when students change } }
@Composable fun MyScreen(state: ViewState) { val students by remember(state.students) { mutableStateOf(state.students) } val teachers by remember(state.teachers) { mutableStateOf(state.teachers) }
LazyColumn { items(students) { student -> // Only recomposes when students change } } }
The best approach depends on your specific needs:
Use approach #1 if you want to keep single state but need derived values Use approach #2 if the lists are updated independently and you want clear separation Use approach #3 if you want a simpler solution and don't need the overhead of StateFlow