Пример приложения с VieModel

Последнее обновление: 16.04.2024

Рассмотрим примере применения ViewModel на простом примере:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.unit.sp
import androidx.lifecycle.ViewModel

import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.ui.text.input.KeyboardType
import androidx.lifecycle.viewmodel.compose.viewModel


class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Main()
        }
    }
}

data class User(val name: String, val age: Int)
class UserListViewModel: ViewModel() {

    val users = mutableStateListOf<User>(User("Tom", 39), User("Bob", 43))
    var userName by mutableStateOf("")
    var userAge by mutableStateOf(0)
    fun addUser(){
        users.add(User(userName, userAge))
    }
    fun changeName(value: String){
        userName = value
    }
    fun changeAge(value: String){
        userAge = value.toIntOrNull()?:userAge
    }
    fun deleteUser(user: User){
        users.remove(user)
    }
}
@Composable
fun Main(vm: UserListViewModel = viewModel()) {
    Column {
        UserData(vm.userName, vm.userAge, changeName = {vm.changeName(it)}, changeAge = {vm.changeAge(it)}, add={vm.addUser()})
        UserList(users = vm.users, delete = {vm.deleteUser(it)})
    }
}
@Composable
fun UserList(users:List<User>, delete:(User)->Unit) {
    LazyColumn(Modifier.fillMaxWidth()) {
        items(users) {u ->
            Text(u.name, Modifier.padding(start=12.dp), fontSize = 25.sp)
            Text(u.age.toString(), Modifier.padding(start=12.dp), fontSize = 22.sp)
            TextButton(onClick = {delete(u)}) {
                Text("Delete", fontSize = 22.sp)
            }
        }
    }
}
@Composable
fun UserData(userName: String, userAge:Int, changeName:(String)->Unit, changeAge:(String)->Unit, add:()->Unit){
    Column{
        OutlinedTextField(value = userName, modifier=Modifier.padding(8.dp), label = {Text("Enter a name")}, onValueChange = {changeName(it)})
        OutlinedTextField(value = userAge.toString(), modifier=Modifier.padding(8.dp), label = {Text("Enter an age")},
            onValueChange = {changeAge(it)},
            keyboardOptions = KeyboardOptions(keyboardType= KeyboardType.Number)
        )
        Button(onClick = { add() }, Modifier.padding(8.dp)) {
            Text("Create", fontSize = 22.sp)
        }
    }
}

Прежде всего здесь определяется класс User - модель данных, с которыми мы будем работать:

data class User(val name: String, val age: Int)

Данный класс представляет пользователя. Свойство name представляет его имя , а age - возраст.

Для работы с данными определена модель представления UserListViewModel. Она управляет списком пользователей, в который мы можем добавить других пользователей или, наоборот, удалить из него пользователей. Непосредственно сам список пользователей хранится в переменной users. По умолчанию в этот список добавлено 2 объекта:

val users = mutableStateListOf<User>(User("Tom", 39), User("Bob", 43))

Для добавления нового пользователя определяются две переменных - для имени и возраста:

var userName by mutableStateOf("")
var userAge by mutableStateOf(0)

Для управления данными также определяется ряд функций:

fun addUser(){
    users.add(User(userName, userAge))
}
fun changeName(value: String){
    userName = value
}
fun changeAge(value: String){
    userAge = value.toIntOrNull()?:userAge
}
fun deleteUser(user: User){
    users.remove(user)
}

В функции addUser добавляем нового пользователя, используя переменные name и age. В функции deleteUser получаем удаляемого пользователя и удаляем его из списка. И функции changeName и changeAge предназначены для изменения переменных name и age соответственно. Обратите внимание, что в changeAge передается строка, которую надо преобразоваь в число.

Для создания формы ввода данных нового пользователя определен компонент UserData с двумя текстовыми полями для имени и возраста:

fun UserData(userName: String, userAge:Int, changeName:(String)->Unit, changeAge:(String)->Unit, add:()->Unit){
    Column{
        OutlinedTextField(value = userName, modifier=Modifier.padding(8.dp), label = {Text("Enter a name")}, onValueChange = {changeName(it)})
        OutlinedTextField(value = userAge.toString(), modifier=Modifier.padding(8.dp), label = {Text("Enter an age")},
            onValueChange = {changeAge(it)},
            keyboardOptions = KeyboardOptions(keyboardType= KeyboardType.Number)
        )
        Button(onClick = { add() }, Modifier.padding(8.dp)) {
            Text("Create", fontSize = 22.sp)
        }
    }
}

При изменении введенных данных в текстовых полях будут вызываться функции changeName и changeAge, которые получают введенное значение. А при нажатии на кнопку будет вызываться функция addUser, которая добавит нового пользователя.

Для вывода списка предназначен компонент UserList:

@Composable
fun UserList(users:List<User>, delete:(User)->Unit) {
    LazyColumn(Modifier.fillMaxWidth()) {
        items(users) {u ->
            Text(u.name, Modifier.padding(start=12.dp), fontSize = 25.sp)
            Text(u.age.toString(), Modifier.padding(start=12.dp), fontSize = 22.sp)
            TextButton(onClick = {delete(u)}) {
                Text("Delete", fontSize = 22.sp)
            }
        }
    }
}

Здесь для каждого пользователя в списке создается пара текстовых меток для вывода имени и возраста с кнопкой удаления, по нажатию на которую будет вызываться функция deleteUser.

И оба этих компонента вызываются в компоненте верхнего уровня Main, который получает ViewModel и передает ее данные в компоненты:

@Composable
fun Main(vm: UserListViewModel = viewModel()) {
    Column {
        UserData(vm.userName, vm.userAge, changeName = {vm.changeName(it)}, changeAge = {vm.changeAge(it)}, add={vm.addUser()})
        UserList(users = vm.users, delete = {vm.deleteUser(it)})
    }
}

В итоге приложения отобразит список, в который мы сможем добавлять новые данные:

ViewModel в мобильном приложении на Jetpack Compose на Kotlin на Android
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850