SavedStateHandle 기록용 포스팅
SavedStateHandle 사용에 대한 단순 기록 용 포스팅입니다.
확인할 내용?
SavedStateHandle은 Activity와 Fragment에서 어떻게 실제로 동작되는가?
에제 ViewModel
CountSavedStateViewModel
class CountSavedStateViewModel(
private val handle: SavedStateHandle
) : ViewModel() {
companion object {
private const val COUNTER = "counter"
}
private var count1 = 0
private val count2 get() = handle.get<Int>(COUNTER) ?: 0
//private val countLiveData = handle.getLiveData<Int>(COUNTER)
fun plusCount() {
++count1
handle.set(COUNTER, count2 + 1)
}
fun showCountLog() {
Log.d("MyTag", "-------showCountLog-------")
Log.d("MyTag", "count1 : $count1, count2 : $count2")
handle.keys().forEach {
Log.d("MyTag", "key : $it, value : ${handle.get<Any>(it)}")
}
}
fun clear() {
Log.d("MyTag", "-------clear------")
handle.keys().forEach {
Log.d("MyTag", "delete key : $it")
handle.remove<Any>(it)
}
}
override fun onCleared() {
super.onCleared()
Log.d("MyTag", "CountSavedStateViewModel onCleared")
}
}
예제 화면
Activity에서 선언
private val savedStateViewModel2 by viewModels<CountSavedStateViewModel> {
SavedStateViewModelFactory(application, this, intent.extras)
}
Fragment에서 선언
private val savedStateViewModel2 by viewModels<CountSavedStateViewModel> {
SavedStateViewModelFactory(activity?.application, this, arguments)
}
SavedStateViewModelFactory의 3번째 인자로 bundle을 넘깁니다. 이때 넘기는 bundle은 Acitivty나 Fragment가 처음 생성되었을 때 가지고 있는 bundle입니다. 넘겨주지 않을 경우 SavedStateHandle에 반영되지 않습니다.
시스템의 의한 종료 테스트를 위한 명령어
앱을 홈으로 이동시킨 후 아래 명령어를 실행하면 해당 프로세스를 강제로 종료시킵니다. 즉 메모리에서 ViewModel을 제거합니다.
> adb shell am kill {package name}
테스트 결과
1. 시스템의 의한 종료를 했을 경우 count2의 값은 유지되는가?
-> Activity의 경우 유지되지만 Fragment의 경우 유지되지 않는다.
2. MainActivity에서 SINGLE_TOP 플래그로 MainActivity를 또 호출하면?
startActivity(
Intent(this, MainActivity::class.java).apply {
putExtra(MY_PARAM, "hello blackjin from activity")
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
)
-> onNewIntent를 실행하게 되며 여기서 받아온 Intent는 다른 Intent이므로 SavedState에 자동으로 반영되지 않는다.
3. 라이브 데이터로 사용할 경우 라이브 데이터의 값을 변경하면 SavedState의 값도 변하는가?
private val countLiveData = handle.getLiveData<Int>(COUNTER)
-> LiveData 값을 변경하면 SavedState 값도 같이 변한다.
4. SavedState의 key를 remove 하면 어떻게 될까?
-> SavedState의 key에 해당하는 값은 제거된다.
-> handle.remove<Any>(COUNTER) 한 경우 countLiveData의 값을 넣어줘도 아무 동작하지 않는다.
-> 라이브 데이터를 다시 사용하고 싶다면 handle.set의 과정이 있어야 된다.
<사용예제>
https://github.com/dlwls5201/ViewModelExample/tree/main
<참고자료>