State

State

 1class TodoListViewModel : ViewModel() {
 2
 3    private val _todos = MutableStateFlow(mutableListOf<Todo>()) // private mutable state flow
 4    val todos: StateFlow<List<Todo>> = _todos.asStateFlow() // publicly exposed as read-only state flow
 5
 6    fun getTodo(id: UUID): Todo? {
 7        return _todos.value.firstOrNull { it.id == id }
 8    }
 9
10    fun upsert(todo: Todo) {
11        val existingIndex = todos.value.indexOfFirst { it.id == todo.id }
12        if (existingIndex >= 0) {
13            _todos.value[existingIndex] = todo
14        } else {
15            _todos.value.add(todo)
16        }
17        _todos.value = _todos.value.toMutableList()
18    }
19}
20
21@Composable
22fun TodoNavHost(modifier: Modifier = Modifier) {
23    val todoListViewModel: TodoListViewModel = viewModel()
24    val navController = rememberNavController()
25    return NavHost(
26        navController = navController,
27        startDestination = "todo-list"
28    ) {
29        composable(route = "todo-list") {
30            TodoListScreen(
31                todoListViewModel = todoListViewModel,
32                onCreate = { navController.navigate(route = "todo-detail/new") },
33                onUpdate = { id -> navController.navigate(route = "todo-detail/$id")},
34                modifier = modifier
35            )
36        }
37        composable(route = "todo-detail/{id}") { backStackEntry ->
38            val id = backStackEntry.arguments?.getString("id")
39                .takeIf { it != "new" }
40                ?.let { UUID.fromString(it) } ?: UUID.randomUUID()
41            TodoDetailScreen(
42                todoListViewModel = todoListViewModel,
43                id = id,
44                navigateBack = { navController.popBackStack() },
45                modifier = modifier
46            )
47        }
48    }
49}
50
51@Composable
52fun TodoListScreen(
53    todoListViewModel: TodoListViewModel,
54    onCreate: () -> Unit,
55    onUpdate: (id: UUID) -> Unit,
56    modifier: Modifier = Modifier
57) {
58    val todos by todoListViewModel.todos.collectAsState()
59    Column(modifier = modifier) {
60        Text(text = "Text List")
61        todos.map {
62            TodoListItem(todo = it, onUpdate = onUpdate)
63        }
64        Button(onClick = onCreate) {
65            Text(text = "Create")
66        }
67    }
68}
69
70@Composable
71fun TodoDetailScreen(
72    todoListViewModel: TodoListViewModel,
73    id: UUID,
74    navigateBack: () -> Unit,
75    modifier: Modifier = Modifier
76) {
77    val todo = todoListViewModel.getTodo(id)
78    var text by remember { mutableStateOf(todo?.text ?: "") }
79    Column(modifier = modifier) {
80        Text(text = "Text Detail")
81        OutlinedTextField(value = text, onValueChange = { text = it })
82        Button(onClick = {
83            todoListViewModel.upsert(Todo(id = id, text = text))
84            navigateBack()
85        }) {
86            Text(text = "Save")
87        }
88    }
89}

Tutorials