UI 상태 저장에서 항상 언급되듯이 ViewModel 객체가 구성 변경사항을 처리할 수 있으므로 개발자는 configuration change와 같은 예외 상황에 신경 쓸 필요가 없습니다. 그러나 시스템에서 시작된 프로세스 중단을 처리해야 한다면 onSaveInstanceState()를 백업으로 사용할 수 있습니다.
일반적으로 UI 상태는 Activity가 아니라 ViewModel 객체에 저장되거나 참조됩니다. 따라서 onSaveInstanceState()를 사용하기 위해서는 저장된 상태 값에 대해 개발자를 대신해 처리할 것이 필요합니다.
Saved State module을 사용하면 ViewModel 객체는 생성자를 통해 SavedStateHandle 객체를 수신합니다. 이 객체는 저장된 상태에 객체를 작성하고 저장된 상태에서 객체를 검색할 수 있게 하는 키-값 맵입니다. 이러한 값은 시스템에서 프로세스가 중단된 후에도 유지되며 동일한 객체를 통해 계속 사용할 수 있습니다.
기본적으로 SavedStateHandle은 SavedStateViewModelFactory를 통해 ViewModel에 주입되며, 이는 ViewModel에 데이터를 전달하는 좋은 방법입니다.
Hilt를 사용하면 ViewModel의 생명 주기에 대해 더욱 세밀하게 조정할 수 있습니다. Hilt에서는 ViewModelComponent를 이용하여 ViewModel의 생명 주기에 대한 디펜던시를 관리할 수 있습니다.
먼저 ViewModelComponent를 살펴보면:
@Builder
public interface ViewModelComponentBuilder {
ViewModelComponentBuilder savedStateHandle(@BindsInstance SavedStateHandle handle);
ViewModelComponentBuilder viewModelLifecycle(@BindsInstance ViewModelLifecycle viewModelLifecycle);
ViewModelComponent build();
}
여기서 볼 수 있듯이 ViewModelComponentBuilder에서는 SavedStateHandle과 ViewModelLifecycle 객체를 바인드하는 방법을 제공합니다. 이는 ViewModel의 생명 주기 및 상태를 관리하는 데 필요한 모든 정보를 포함하고 있습니다.
이제 ViewModel에서 SavedStateHandle을 이용하는 방법을 알아봅시다.
포포리 프로젝트의 AddPhotoViewModel을 예제로 들어보겠습니다.
@HiltViewModel
class AddPhotoViewModel @Inject constructor(
private val photoRepository: PhotoRepository,
private val savedStateHandle: SavedStateHandle
) : ViewModel()
위의 예에서 AddPhotoViewModel는 Hilt에서 제공하는 @HiltViewModel 어노테이션을 사용하여 표시됩니다. @HiltViewModel은 Hilt가 이 ViewModel의 의존성을 관리하도록 지시하는 역할을 합니다.
SavedStateHandle은 생성자를 통해 ViewModel에 주입되며, 이를 통해 Intent Extra에 접근하거나 저장된 상태를 복구하는 등의 작업을 수행할 수 있습니다.
예를 들어, savedStateHandle를 사용하여 intent extra에 포함된 특정 키를 가진 데이터에 접근할 수 있습니다.
val photoId = savedStateHandle.get<String>("photo_id")
여기서 "photo_id"는 Intent에서 전달된 extra의 키입니다.
이처럼 SavedStateHandle을 통해 상태 관리 및 Intent Extras에 대한 접근이 가능해지면 아래와 같은 중복코드를 줄일 수 있습니다.
private val _name = MutableStateFlow("")
val name = _name.asStateFlow()
fun updateName(name:String){
_name.value = name
}
private val _description = MutableStateFlow("")
val description = _description.asStateFlow()
fun updateDescription(description:String){
_description.value = description
}
private val _location = MutableStateFlow("")
val location = _location.asStateFlow()
fun updateLocation(location:String){
_location.value = location
}
이 기능들은 앱의 안정성을 크게 향상시키며, 개발자의 작업을 훨씬 간편하게 만들어 줍니다!! 뽀뽀리 화이팅~!!
관련 공식 링크: https://developer.android.com/topic/libraries/architecture/viewmodel/viewmodel-savedstate
앱의 안정성을 증가시키는 SavedStateHandle에 대해서 잘 이해하고 갑니다 고마워요!