개발일지

Android in A..Z - Lifecycle (ViewModel with SavedStateHandle) 본문

Android (안드로이드)/Lifecycle

Android in A..Z - Lifecycle (ViewModel with SavedStateHandle)

강태종 2021. 3. 20. 01:10

ViewModel with SavedStateHandle

ViewModel은 UI Data를 안전하게 보관하는 방법의 하나입니다. onSavedInstaceState()를 사용하지 않고 데이터를 쉽게 저장/복원 할 수 있고 메모리에 저장하기 때문에 SavedStateHandle에 비해 빠릅니다. 하지만 메모리에 저장하기 때문에 Android Framework에서 메모리를 회수하면 저장된 값을 잃습니다. 하지만 SavedStateHandle은 디스크에 직렬화하여 저장하기 때문에 값을 유지할 수 있습니다.

=> ViewModel에서는 이러한 문제점을 해결하기 위해 SavedStateHandle을 쉽게 조작할 수 있도록 도와줍니다.

  ViewModel SavedInstanceState Persistent Storage
저장소 위치 메모리 내 디스크에 직렬화 디스크 또는 네트워크 내
구성 변경 시에도 유지
시스템에서 시작된 프로세스 중단 시에도 유지 아니요
사용자의 완전한 활동 닫기/onFinish() 시에도 유지 아니요 아니요
데이터 제한 복잡한 객체도 괜찮지만 사용 가능한 메모리에 의해 공간이 제한됨 원시(primitive) 유형 및 문자열과 같은 단순하고 작은 객체만 해당 디스크 공간 또는 네트워크 리소스에서 검색하는 비용/시간에 의해서만 제한됨
읽기/쓰기 시간 빠름(메모리 액세스만) 느림(직렬화/역직렬화 및 디스크 액세스 필요) 느림(디스크 액세스 또는 네트워크 트랜잭션 필요)


Dependency

    def lifecycle_version = "2.3.0"

    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"

CounterViewModel

class CounterViewModel(
    private val stateHandle: SavedStateHandle,
    initialCount: Int = 0
) : ViewModel() {
    companion object {
        private const val COUNT = "count"
    }

    val counterLiveData by lazy { stateHandle.getLiveData(COUNT, initialCount) }

    fun increase() {
        stateHandle[COUNT] = (counterLiveData.value ?: 0) + 1
    }

    fun reset() {
        stateHandle[COUNT] = 0
    }
}

CounterViewModelFactory

@Suppress("UNCHECKED_CAST")
class CounterViewModelFactory(
        private val initialCount: Int = 0,
        owner: SavedStateRegistryOwner,
        defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {
    override fun <T : ViewModel?> create(key: String, modelClass: Class<T>, handle: SavedStateHandle): T {
        return CounterViewModel(handle, initialCount) as T
    }
}

CounterFragment

class CounterFragment : BaseFragment<FragmentCounterBinding>(R.layout.fragment_counter) {
    private val viewModel by viewModels<CounterViewModel> { CounterViewModelFactory(0, this) }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.counterLiveData.observe(viewLifecycleOwner) {
            binding.count = it
        }
    }

    override fun init() {
        initSupportActionbar()
        initOnCount()
        initOnReset()
    }

    private fun initSupportActionbar() {
        setSupportActionBar(binding.toolbar)
    }

    private fun initOnCount() {
        binding.setOnCount {
            viewModel.increase()
        }
    }

    private fun initOnReset() {
        binding.setOnReset {
            viewModel.reset()
        }
    }
}

 

ADB Process Kill

adb shell am kill com.taetae98.lifecycle

 

Git (예제소스)

github.com/KangTaeJong98/Example/tree/main/Android/LifeCycle

 

KangTaeJong98/Example

My Example Code. Contribute to KangTaeJong98/Example development by creating an account on GitHub.

github.com

 

Comments