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