정상에서 IT를 외치다

SavedStateHandle 기록용 포스팅 본문

안드로이드

SavedStateHandle 기록용 포스팅

Black-Jin 2021. 7. 8. 18:53
반응형

 

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

 

<참고자료>

Pluu Dev - Android 상태 저장의 기본에서 SavedState까지

반응형
Comments