시배's Android

Android | Deep dive into SavedStateHandle 본문

Android/Android

Android | Deep dive into SavedStateHandle

si8ae 2023. 8. 16. 22:05
 

Android : Deep dive into SavedStateHandle | Romman Sabbir

SavedStateHandle: APIs, how it works with ViewModel and survive the Configuration changes.

rommansabbir.com

Basic

AndroidX 라이브러리에서 도입된 SavedStateHandle은 Android 애플리케이션에서 구성 변경 중에 데이터를 유지하고 복원하는 편리한 방법을 제공합니다. SavedStateHandle은 이 기능을 구현하기 위해 여러 핵심 구성 요소와 메커니즘을 활용합니다. Android SavedStateHandle의 내부 구현을 탐색하고 작동 방식을 이해해보겠습니다.

SavedStateHandle은 Android 아키텍처 컴포넌트의 일부이며, ViewModel 클래스와 긴밀하게 통합됩니다.

이는 구성 변경을 통해 유지해야 하는 데이터의 키-값 쌍을 저장합니다.

이러한 키-값 쌍은 ViewModel의 수명 주기 동안 SavedStateHandle에 의해 저장되고 검색됩니다.

- 쌍이 추가되거나 수정될 , SavedStateHandle 내부적으로 LinkedHashMap 업데이트합니다. 마찬가지로 검색 , SavedStateHandle LinkedHashMap에서 해당 키를 찾아서 값이 있는 경우 값을 반환합니다.

Public APIs

// To set a value
fun <T> set(key: String, value: T?)

// To get a value
fun <T> get(key: String): T? 

// To remove a value
fun <T> remove(key: String): T? 

// To find a key present or not
fun contains(key: String): Boolean 

// To get a value as LiveData
fun <T> getLiveData(key: String): MutableLiveData<T>

// To get a value as LiveData with a initial value if has null value
fun <T> getLiveData(key: String, initialValue: T): MutableLiveData<T>

// To get a value as StateFlow with a initial value
fun <T> getStateFlow(key: String, initialValue: T): StateFlow<T>

Notes

  • 모든 Public API는 MainThread에서 호출되어야 합니다.
  • <T>는 지원되는 종류의 모든 객체를 의미합니다.
  • 값을 저장하기 전에 set() 메서드는 값이 Supported Objects List에 나열되어 있는지 확인하기 위해 validateValue(value)를 호출합니다. 그렇지 않으면 IllegalArgumentException을 throw합니다.
  Boolean::class.javaPrimitiveType, BooleanArray::class.java,
  Double::class.javaPrimitiveType, DoubleArray::class.java,
  Int::class.javaPrimitiveType, IntArray::class.java,
  Long::class.javaPrimitiveType, LongArray::class.java,
  String::class.java, Array<String>::class.java,
  Binder::class.java, Bundle::class.java,
  Byte::class.javaPrimitiveType, ByteArray::class.java,
  Char::class.javaPrimitiveType, CharArray::class.java,
  CharSequence::class.java, Array<CharSequence>::class.java,
  ArrayList::class.java, Float::class.javaPrimitiveType,
  FloatArray::class.java, Parcelable::class.java,
  Array<Parcelable>::class.java, Serializable::class.java,
  Short::class.javaPrimitiveType, ShortArray::class.java,
  SparseArray::class.java, Size::class.java
  Int::class.javaPrimitiveType, SizeF::class.java

How does it survive the Configuration changes?

  • SavedStateHandle은 ViewModel과 관련이 있습니다. SavedStateHandle은 주로 ViewModel 인스턴스 내에서 상태를 관리하기 위한 내부 메커니즘으로 설계되었습니다. 이는 구성 변경 간에 데이터를 유지하고 복원하기 위한 컨테이너로 작동합니다.

SavedStateHandle은 Android의 ViewModel 수명 주기와 Android 프레임워크의 기반 아키텍처를 활용하여 Android에서 구성 변경을 이겨냅니다. 화면 회전과 같은 구성 변경이 발생하면 시스템은 연관된 Activity나 Fragment를 파괴하고 다시 생성합니다. 그러나 ViewModel과 해당 SavedStateHandle은 이 과정에 영향을 받지 않습니다.

  • ViewModel 초기화: Activity나 Fragment가 생성될 때, 관련된 ViewModel의 새 인스턴스가 생성되거나 검색됩니다. 이 초기화는 일반적으로 Activity나 Fragment의 onCreate() 메서드에서 발생합니다.
  • SavedStateHandle Association: ViewModel 초기화 중에 SavedStateHandle은 ViewModel과 연관됩니다. 이 연관은 일반적으로 의존성 주입 프레임워크나 ViewModelProvider를 통해 수립됩니다.
  • SavedStateHandle 생성: SavedStateHandle은 ViewModel의 저장된 상태를 나타내는 Bundle로 초기화됩니다. 이 Bundle은 프레임워크에 의해 자동으로 제공되며, 구성 변경 간에 유지되어야 하는 데이터를 나타냅니다.
  • Bundle 보존: 구성 변경이 발생하면 시스템은 Activity나 Fragment를 파괴하지만 ViewModel 인스턴스와 해당 SavedStateHandle은 유지됩니다. SavedStateHandle과 연관된 Bundle은 시스템에 의해 보존됩니다.
  • ViewModel 재생성: 구성 변경 후에는 새로운 Activity나 Fragment 인스턴스가 생성되며, ViewModel이 다시 생성됩니다. SavedStateHandle도 이전 인스턴스의 보존된 Bundle을 사용하여 다시 생성됩니다.
  • 상태 복원: ViewModel과 SavedStateHandle이 다시 생성되면, SavedStateHandle에 저장된 값은 보존된 Bundle에서 자동으로 복원됩니다. 이를 통해 구성 변경 간에 상태가 유지됩니다.

In a nutshell

  • SavedStateHandle는 LinkedHashMap을 활용하여 고유한 키에 따라 지원되는 객체를 보유하는 컨테이너입니다. 간단한 키-값 개념이지만 매우 강력합니다.
  • ViewModelProvider에 의해 제공되는 ViewModel 인스턴스는 Activity와 연관됩니다.
  • 모든 ViewModel 인스턴스에는 SavedStateHandle의 인스턴스가 포함되어 있습니다.
  • ViewModel이 Activity 수명 주기에 바인딩되지 않기 때문에 구성 변경이 발생할 때 ViewModelProvider는 SavedStateHandle 상태를 포함한 관련된 Activity와 함께 인스턴스를 복원합니다.