savedStateHandle로 ViewModel의 상태를 저장
PR리뷰로 (Activity or Fragment)에서 사용하던 savedInstanceState를 ViewModel의 savedStateHandle로 사용해달라는 요청이 왔습니다.
검색하면서 궁금했던 점
1. 아래 글을 보면 savedStateHandle.set과 get이 있습니다.
따로 set/get은 하지 않아도 된다고 함.
savedStateHandle 안에 intent로 넘어온 값이 들어있음
로그를 직접 찍어보니
Fragment의 savedInstanceState는 null이고 (true값)
ViewModel의 savedStateHandle는 데이터가 있었다. (intent안에 있는 값들이다.)
그래서 뷰 모델의 LifeCycle은 Activity보다 크기 때문에
뷰 모델이 Destroy되면 화면이 아예 종료된것으로 판단하여,
override fun onSaveInstanceState(outState: Bundle) 부분에서 따로 데이터를 저장해 줄 필요가 없다. (뷰모델은 유지 되기 때문)
하지만, 화면도 종료되고 뷰모델도 종료가 되었는데 데이터를 추후에 불러와야 한다면 따로 저장 처리를 해야함.
예) 알림장 작성중 -> 화면 종료 -> 다시 알림장 작성화면 (작성하던 내용 입력 되도록 하는 예제)
2. 검색 내용에 ViewModel을 SavedStateViewModelFactory로 생성해야 한다고 되어있다.
요새에는 by로 위임하여 생성하기 때문에 내부적으로 알아서 생성 해주는 것 같다.
savedStateHandle 검색 내용
ViewModel을 위한 saved state 모듈은 lifecycle 버전 2.2.0에서 추가 되었다.
savedStateHandle을 ViewModel에서 다루기 위해서는
savedStateHandle을 받는 생성자를 ViewModel에 포함해야 한다.
class MainViewModel(val savedStateHandle: SavedStateHandle) : ViewModel() {
...
}
SavedStateHandle을 받도록 ViewModel 인스턴스를 생성하려면
AbstractSavedStateViewModelFactory를 확장하는 Factory 클래스를 만들어야 한다.
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
...
viewModel = ViewModelProvider(this, SavedStateViewModelFactory(application, this)).get(MainViewModel::class.java)
}
}
ViewModel의 SavedStateHandle을 이용하여 간단한 데이터를 저장하고 복원하는 코드를 구현할 수 있다.
사용법) 정수형 count 변수의 상태를 저장하고 복원하는 코드다.
class MainViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
var count = 0
set(value) {
savedStateHandle.set("count",value)
field = value
}
init {
savedStateHandle.get<Int>("count")?.run {
count = this
}
}
}
테스트 방법
시스템에 의한 Activity소멸 케이스를 테스트 하고 싶다면,
개발자 모드 > 액티비티 유지안함 옵션을 활성화 하자.
백그라운드로 진입하는 순간 바로 Activity가 소멸되고, 포어그라운드로 재진입했을 때 새로운 Activity가 생성되는 것을 확인할 수 있다. 또한 개발자 모드에서 백그라운드 프로세스 개수에 제한을 거는 방법도 유효하다.
참조 :
'코딩 > 코드리뷰' 카테고리의 다른 글
자바 함수 및 exception 발생 여부 (0) | 2023.04.11 |
---|---|
Observable, Single 비교 (0) | 2022.01.27 |
Observable subscribeOn, observeOn 스레드 (0) | 2022.01.27 |
TakeIf로 값 넣기 (0) | 2021.12.20 |
변수 3개 선언하기 (0) | 2021.11.23 |