I'm trying to set up a basic MVI system in Kotlin, but I have very little experience with user interfaces or real-time variable updates. The example I'm trying to build simply has a bool named isOn and a float named score, both of which you should be able to adjust from a view. Currently I can't drag the slider or change the state of the bool.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activitypose.setContent
import androidxpose.foundation.clickable
import androidxpose.foundation.layout.*
import androidxpose.material3.*
import androidxpose.runtime.*
import androidxpose.ui.Alignment
import androidxpose.ui.Modifier
import androidxpose.ui.text.style.TextAlign
import androidxpose.ui.unit.dp
import androidx.lifecycle.ViewModel
// MVI State
data class ViewState(
val isOn: Boolean = false,
val score: Float = 0.50f
)
// MVI Intent (User Actions)
sealed class ViewIntent {
data class SetScore(val newScore: Float) : ViewIntent()
object ToggleIsOn : ViewIntent()
}
// MVI ViewModel (Handles state & processes intents)
class MVIViewModel : ViewModel() {
private var _state by mutableStateOf(ViewState())
val state: ViewState get() = _state
fun processIntent(intent: ViewIntent) {
when (intent) {
is ViewIntent.SetScore -> {
_state = _state.copy(score = intent.newScore)
}
ViewIntent.ToggleIsOn -> {
_state = _state.copy(isOn = !_state.isOn)
}
}
}
}
// Composable View
@Composable
fun MVIView(viewModel: MVIViewModel = MVIViewModel()) {
val state = viewModel.state
Column(
modifier = Modifier.fillMaxSize().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = if (state.isOn) "State: ON" else "State: OFF",
style = MaterialTheme.typography.headlineMedium,
textAlign = TextAlign.Center,
modifier = Modifier
.clickable { viewModel.processIntent(ViewIntent.ToggleIsOn) }
.padding(16.dp)
)
Spacer(modifier = Modifier.height(16.dp))
Text("Score: ${state.score}")
Slider(
value = state.score,
onValueChange = { viewModel.processIntent(ViewIntent.SetScore(it)) },
valueRange = 0.50f..100f
)
}
}
// Main Activity
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
MVIView()
}
}
}
}