Android 에서 상태를 저장하고 관리하기 위해 사용되는 전형적인 수단
// BAD
@Composable
fun LoginScreen() {
**val viewModel: LoginViewModel = hiltViewModel() <- 이 부분**
val state = viewModel.state
Column {
if (state.isLoading) {
CircularProgressIndicator()
}
Button(onClick = { viewModel.login() }) {
Text(text = "Login")
}
}
}
뷰모델이 Screen의 생성자에 주입되고 있음. 이러한 방식은 하기 단점이 존재.
// GOOD
sealed interface LoginEvent {
object Login: LoginEvent
// More events...
}
/**
* 각각의 ViewModel은 Screen 의 State 객체를 가지고 있음.
*/
class LoginViewModel: ViewModel() {
**var state by mutableStateOf(LoginState())** <- LoginScreen의 State
private set
fun onEvent(event: LoginEvent) {
when(event) {
is LoginEvent.login -> { /* Handle login */ }
// ,,,
}
}
}
---
/**
* Screen을 래핑하는 Composable. 이 곳에서 ViewModel을 안전하게 초기화.
*/
@Composable
fun LoginScreenRoot() {
val viewModel = hiltViewModel<LoginViewModel>()
LoginScreen(
state = viewModel.state,
onEvent = viewModel::onEvent
)
}
/**
* Screen은 State 객체와 onEvent 함수를 노출함.
* onEvent 함수는 사용자가 수행하는 다양한 액션들을 수신하는 역할.
*/
@Composable
fun LoginScreen(
**state: LoginState,
onEvent: (LoginEvent) -> Unit**
) {
Column {
if (state.isLoading) {
CircularProgressIndicator()
}
Button(onClick = { onEvent(LoginEvent.Login) }) {
Text(text = "Login")
}
// ...
}
}