ViewModel - ํ๋ฉด ๋ฐ์ผ๋ก ์ํ ์ฎ๊ธฐ๊ธฐ
์ง๋ ๊ธ์์ todoList๋ฅผ TodoApp์ผ๋ก ๋์ด์ฌ๋ ค์ ๋ ํ๋ฉด์ด ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ฒ ๋ง๋ค์๋ค. ๊ทผ๋ฐ ๋์ ๋งํ๋ ๊ฒ์ฒ๋ผ ๋ ๊ฐ์ง๊ฐ ๋จ์์๋ค. ํ๋ฉด์ ํ์ ํ๋ฉด ๋ฐ์ดํฐ๊ฐ ๋ ์๊ฐ๊ณ , ๋ก์ง์ด UI ์ฝ๋๋ ๋ค์์ฌ ์๋ค.
ํ๋ฉด์ ํ์ ํด๋ณด๋ฉด
@Composable
fun TodoApp() {
val todoList = remember {
mutableStateListOf(
Todo(id = 1, title = "์ฅ๋ณด๊ธฐ"),
Todo(id = 2, title = "์ด๋ํ๊ธฐ"),
Todo(id = 3, title = "์ฑ
์ฝ๊ธฐ")
)
}
// ...
}[์ด๋ฏธ์ง: ํ ์ผ์ ๋ช ๊ฐ ์ถ๊ฐํ ๋ค ํ๋ฉด์ ํ์ ํด์, ์ถ๊ฐํ๋ ํญ๋ชฉ์ด ์ฌ๋ผ์ง๊ณ ์ด๊ธฐ 3๊ฐ๋ง ๋จ์ ๋ชจ์ต]
์ถ๊ฐํ๋ ํ ์ผ์ด ๋ค ์ฌ๋ผ์ง๊ณ ์ฒ์ 3๊ฐ๋ง ๋จ๋๋ค. rememberSaveable์ ์ฐ๋ฉด ๋์ง ์๋ ์ถ๊ฒ ์ง๋ง, rememberSaveable์ Int, String์ฒ๋ผ ๋จ์ํ ๊ฐ์ด๋ Parcelable ์ ๋๋ง ๋ฐ๋ก ์ ์ฅํ ์ ์๊ณ , Todo๋ฅผ ๋ด์ ๋ฆฌ์คํธ ๊ฐ์ ๊ฑด ์ ์ฅ ๋ฐฉ๋ฒ(Saver)์ ๋ฐ๋ก ๋ง๋ค์ด์ค์ผ ํ๋ค. ๋ฒ๊ฑฐ๋กญ๋ค.
ViewModel - ์กํฐ๋นํฐ๊ฐ ๋ค์ ๋ง๋ค์ด์ ธ๋ ์ด์๋จ๋ ๊ฐ์ฒด
์๋๋ก์ด๋์๋ ์ด ๋ฌธ์ ๋ฅผ ์ํด ์๋๋ถํฐ ์๋ ๋๊ตฌ๊ฐ ์๋ค. ViewModel์ด๋ค.
class TodoViewModel : ViewModel() {
val todoList = mutableStateListOf(
Todo(id = 1, title = "์ฅ๋ณด๊ธฐ"),
Todo(id = 2, title = "์ด๋ํ๊ธฐ"),
Todo(id = 3, title = "์ฑ
์ฝ๊ธฐ")
)
private var nextId = 4
fun addTodo(title: String) {
todoList.add(Todo(id = nextId, title = title))
nextId += 1
}
fun toggleDone(id: Int) {
val index = todoList.indexOfFirst { it.id == id }
if (index != -1) {
todoList[index] = todoList[index].copy(isDone = !todoList[index].isDone)
}
}
fun deleteTodo(id: Int) {
todoList.removeAll { it.id == id }
}
}ViewModel์ ์ปดํฌ์ ๋ธ์ด ์๋๋ผ ๊ทธ๋ฅ ํ๋ฒํ ํด๋์ค๋ค. ๋์ ViewModel()์ ์์๋ฐ์ผ๋ฉด, ์๋๋ก์ด๋ ์์คํ
์ด ์ด ๊ฐ์ฒด๋ฅผ ํ๋ฉด ํ์ ๊ฐ์ ๊ตฌ์ฑ ๋ณ๊ฒฝ์๋ ๋ฐ๋ก ๋ณด๊ดํด์ค๋ค. ์กํฐ๋นํฐ๋ ํต์งธ๋ก ํ๊ดด๋๊ณ ์๋ก ๋ง๋ค์ด์ง์ง๋ง, ๊ทธ ์กํฐ๋นํฐ์ ์ฐ๊ฒฐ๋ ViewModel์ ๋ฉ๋ชจ๋ฆฌ์ ๊ทธ๋๋ก ์ด์์๋ค๊ฐ ์๋ก ๋ง๋ค์ด์ง ํ๋ฉด์ ๋ค์ ์ฐ๊ฒฐ๋๋ค.
์ปดํฌ์ ๋ธ์์ ViewModel ์ฐ๊ธฐ
import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun TodoApp(viewModel: TodoViewModel = viewModel()) {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "list") {
composable("list") {
TodoListScreen(
todoList = viewModel.todoList,
onAdd = viewModel::addTodo,
onToggleDone = viewModel::toggleDone,
onDelete = viewModel::deleteTodo,
onTodoClick = { todo -> navController.navigate("detail/${todo.id}") }
)
}
composable("detail/{todoId}") { backStackEntry ->
val todoId = backStackEntry.arguments?.getString("todoId")?.toIntOrNull()
val todo = viewModel.todoList.find { it.id == todoId }
TodoDetailScreen(
todo = todo,
onToggleDone = viewModel::toggleDone,
onBack = { navController.popBackStack() }
)
}
}
}[์ด๋ฏธ์ง: ํ ์ผ์ ์ถ๊ฐํ ๋ค ํ๋ฉด์ ํ์ ํด๋ ์ถ๊ฐํ๋ ํญ๋ชฉ์ด ๊ทธ๋๋ก ๋จ์์๋ ๋ชจ์ต]
viewModel()์ androidx.lifecycle.viewmodel.compose ํจํค์ง์์ ์ ๊ณตํ๋ ํจ์๋ค. ํธ์ถํ๋ฉด ์ด ์ปดํฌ์ ๋ธ์ด ์ํ ์กํฐ๋นํฐ(๋๋ ๋ค๋น๊ฒ์ด์
๋ชฉ์ ์ง) ๋ฒ์์ ๋ฌถ์ธ TodoViewModel ์ธ์คํด์ค๋ฅผ ๋๋ ค์ค๋ค. ํ๋ฉด ํ์ ์ผ๋ก TodoApp์ด ๋ค์ ์คํ๋ผ๋ viewModel()์ ์ ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ง ์๊ณ ์๊น ๊ทธ ์ธ์คํด์ค๋ฅผ ๊ทธ๋๋ก ๋๋ ค์ค๋ค. ๊ทธ๋์ todoList๋ ๊ทธ๋๋ก ์ ์ง๋๋ค.
TodoListScreen๊ณผ TodoDetailScreen ์ชฝ ์ฝ๋๋ ์ง๋ ๊ธ๊ณผ ๊ฑฐ์ ๋๊ฐ๋ค. ๋ฐ๋ ๊ฑด todoList์ ์ฝ๋ฐฑ๋ค์ด ์ด์ TodoApp์ remember ๋์ viewModel์์ ๋์จ๋ค๋ ๊ฒ๋ฟ์ด๋ค. onAdd = viewModel::addTodo์ฒ๋ผ ํจ์ ์ฐธ์กฐ๋ก ๋ฐ๋ก ๋๊ธธ ์ ์์ด์ ์ฝ๋๋ ์คํ๋ ค ์งง์์ก๋ค.
์ง๋ ๊ธ์ ์ํ ํธ์ด์คํ ์ด ํ์๊ณ ์๋?
์๋๋ค. ์คํ๋ ค ๊ทธ ๋๋ถ์ ์ง๊ธ ๋ฐ๋ ๊ฒ ์ ๋ค. TodoListScreen, TodoDetailScreen์ ์ ์ด์ ์๊ธฐ ๋ฐ์ดํฐ๋ฅผ ์ ๊ฐ๊ณ "๊ฐ + ์ฝ๋ฐฑ"๋ง ๋ฐ๋ ๊ตฌ์กฐ์์ด์, ๊ทธ ๊ฐ๊ณผ ์ฝ๋ฐฑ์ด ์ด๋์ ์๋์ง(remember์๋์ง ViewModel์ด์๋์ง)๋ ์ด ์ปดํฌ์ ๋ธ๋ค ์
์ฅ์์๋ ์ ํ ์๊ด์ด ์๋ค. ์ํ๋ฅผ ์ด๋์ ๋์ง ๋ฐ๊ฟ๋ ํ๋ฉด ์ชฝ ์ฝ๋๋ ๊ทธ๋๋ก ์ธ ์ ์๋ค๋ ๊ฒ ์ํ ํธ์ด์คํ
์ ์์ ์ด์๋ค.
์ ๋ฆฌ
remember๋ ์ปดํฌ์ ๋ธ์ด ํ๋ฉด์ ๋ ์๋ ๋์๋ง,ViewModel์ ํ๋ฉด(์กํฐ๋นํฐ)์ด ๋ค์ ๋ง๋ค์ด์ ธ๋ ๋ฐ์ดํฐ๋ฅผ ์ง์ผ์ค๋คviewModel()์ ํธ์ถํ๋ฉด ๊ฐ์ ๋ฒ์ ์์์๋ ํญ์ ๊ฐ์ ์ธ์คํด์ค๋ฅผ ๋๋ ค๋ฐ๋๋ค- ๋ฐ์ดํฐ์ ๊ทธ๊ฑธ ๋ฐ๊พธ๋ ๋ก์ง(
addTodo,toggleDone,deleteTodo)์ViewModel์ ๋ชจ์๋๋ฉด, ์ปดํฌ์ ๋ธ์ "๋ณด์ฌ์ฃผ๊ณ ์์ฒญ๋ง ํ๋" ์ญํ ๋ก ๊ฐ๋ฒผ์์ง๋ค
๊ทผ๋ฐ ์์ง ๋จ์ ๋ฌธ์
์ง๊ธ todoList๋ mutableStateListOf๋ผ์ ๋ฐ๊นฅ์์๋ viewModel.todoList.add(...)์ฒ๋ผ ์ง์ ๊ฑด๋๋ฆด ์ ์๋ค. ViewModel์ ์ฐ๋ ์ด์ ์ค ํ๋๊ฐ "๋ฐ์ดํฐ๋ฅผ ๋ฐ๊พธ๋ ๋ฐฉ๋ฒ์ addTodo, toggleDone ๊ฐ์ ํจ์๋ก๋ง ์ ํํ๊ณ ์ถ๋ค"๋ ๊ฑฐ์๋๋ฐ, ์ง๊ธ์ ๊ทธ ์ ํ์ด ์์ ํ์ง ์๋ค. ๋ ๋ก๋ฉ ์ค์ด๊ฑฐ๋ ์๋ฌ๊ฐ ๋ ์ํ์ฒ๋ผ "์ง๊ธ ํ๋ฉด์ด ์ด๋ค ์ํ์ธ์ง"๋ฅผ ํํํ ๋ฐฉ๋ฒ๋ ์์ง ์๋ค.
๋ค์ ๊ธ์์๋ StateFlow์ UI ์ํ(UiState)๋ฅผ ์จ์ ์ด ๋ถ๋ถ์ ์ ๋ฆฌํด๋ณด๊ฒ ๋ค.
