MVVM Architecture in Kotlin - Counter App
Introduction
- MVVM stands for Model-View-ViewModel.
- It is a design pattern that separates the UI from the business logic.
- It is a variation of the MVC and MVP design patterns.
A simple counter app
The Counter Model
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// CounterModel.kt
data class CounterModel(var count: Int)
class CounterRepository {
private val _counter = CounterModel(0)
fun getCounter() = _counter
fun incrementCounter() {
_counter.count++
}
fun decrementCounter() {
_counter.count--
}
}
- The
CounterModel
data class represents the counter value. - The
CounterRepository
class contains the business logic for the counter app. - It has functions to get the counter value, increment the counter, and decrement the counter.
The Counter ViewModel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class CounterViewModel() : ViewModel() {
private val _repository:CounterRepository = CounterRepository()
private val _count = mutableStateOf(_repository.getCounter().count)
/*val count: Int
get() = _count*/
val count: MutableState<Int> = _count
fun increment() {
_repository.incrementCounter()
_count.value = _repository.getCounter().count
}
fun decrement() {
_repository.decrementCounter()
_count.value = _repository.getCounter().count
}
}
- The
CounterViewModel
class extends theViewModel
class. - It contains the UI logic for the counter app.
- It has a
CounterRepository
instance to interact with the business logic. - It uses a
MutableState
to hold the count value. - It has functions to increment and decrement the count value.
The Counter Screen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Composable
fun CounterApp(viewModel: CounterViewModel) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Count: ${viewModel.count.value}",
fontSize = 24.sp,
fontWeight = FontWeight.Bold
)
// add a space between the text and the buttons
Spacer(modifier = Modifier.height(16.dp))
Row {
Button(onClick = { viewModel.increment() }) {
Text("Increment")
}
Button(onClick = { viewModel.decrement() }) {
Text("Decrement")
}
}
}
}
- The
CounterApp
composable function displays the UI elements for the counter app. - It takes a
CounterViewModel
instance as a parameter. - It displays the count value using the
Text
composable. - It has two
Button
composable elements to increment and decrement the count value. - The
onClick
lambda functions call theincrement
anddecrement
functions of theCounterViewModel
.
The Main Activity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val viewModel: CounterViewModel = viewModel()
KotlinCounterTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
CounterApp(viewModel)
}
}
}
}
}
- The
MainActivity
class is a subclass ofComponentActivity
. - The
onCreate
method sets the content of the activity to aCounterApp
composable. - It creates an instance of the
CounterViewModel
using theviewModel()
function. - The
CounterApp
composable is passed theCounterViewModel
instance.
Conclusion
- The MVVM architecture separates the UI logic from the business logic.
- In this example, the
CounterViewModel
class contains the business logic for the counter app. - The
CounterApp
composable function displays the UI elements and interacts with theCounterViewModel
.
This post is licensed under CC BY 4.0 by the author.