![見出し画像](https://assets.st-note.com/production/uploads/images/19174680/rectangle_large_type_2_9b705499d51dea4d3b9eb77696fb26d0.png?width=1200)
[Android] ViewModel-SavedState-ktx 2.2.0 をリリースしました
# ViewModel-SavedState-ktx とは
ViewModel-SavedState の SavedStateHandle を Delegated Property で簡単に扱えるようにするライブラリです。
# ViewModel-SavedState とは
これまで、UI の状態は onSavedInstanceState で保存され、onCreateで復元されていました。今後、ViewModel-SavedState を使って SavedStateHandleで UI の状態を保存・復元できます。
# なぜ ViewModel-SavedState を使うのか
画面回転などの Configuration Changes が発生した場合、ViewModel は生き続けますが、メモリ不足により OS によって Activity が強制終了されると、ViewModel は破棄されます。 ViewModel-SavedState を使用すると、Activity がOSによって強制終了されたときに ViewModel のプロパティを保存できます。
# ViewModel-SavedState の使い方
## SavedStateHandle の取得方法
ViewModel のコンストラクタ引数で SavedStateHandle を取得できます。
## SavedStateHandle を ViewModel のコンストラクタに渡す方法
Activity または Fragment で `by viewModels()` などを使った場合、自動的に SavedStateHandle が渡されます。ViewModel のコンストラクタ引数が `SavedStateHandle` または `Application, SavedStateHandle` 以外の場合、`by viewModels` に AbstractSavedStateViewModelFactory を継承したファクトリを渡す必要があります。
※ `by viewModels()` を使った場合、`intent.extras` または `arguments` が自動的に渡されていて SavedStateHandle を介してパラメータを受け取ることができます。ファクトリを渡した場合は、必要ならファクトリのコンストラクタに `intent.extras` または `arguments` を渡す必要があります。
## SavedStateHandle の使い方
`SavedStateHandle#get(key)` で値を取得、`SavedStateHandle#set(key, value)` で値を保存できます。値は `intent.extras` または `arguments` で初期化されています。
`SavedStateHandle#getLiveData(key)` で LiveData で値を取得可能です。`SavedStateHandle#getLiveData(key, initialValue)` で初期値を設定することも可能です。LiveData の値を変更した場合は、自動的に SavedStateHandle の値も変更されます。
# ViewModel-SavedState の問題
`SavedStateHandle#get(key)` で値を取得した場合、値を変更した時は `SavedStateHandle#set(key, value)` も呼ぶ必要があります。
SavedStateHandle の使用に key が必要です。また、その key は `intent.extras` または `arguments` のキーと同じキーを使う必要があります。
SavedStateHandle に保存できる型には制限があります。
# ViewModel-SavedState-ktx による解決
Delegated Property で値を変更したら自動的に `SavedStateHandle#set(key, value)` を呼び出します。
SavedStateHandle の使用には key は不要です。代わりにプロパティ名を使用します。Intent と Bundle にプロパティ名を key に指定するための拡張関数を提供しています。
SavedStateHandle に保存できる型と実際に ViewModel で利用する型を相互変換する SavedStateAdapter を使って任意の型を利用できます。
# ViewModel-SavedState-ktx の使い方
プロパティ参照を使った拡張関数で Intent や Bundle にパラメータを渡します。
class SampleActivity : AppCompatActivity(R.layout.sample_activity) {
private val viewModel: SampleViewModel by viewModels()
companion object {
@JvmStatic
fun createIntent(context: Context): Intent = Intent(context, SampleActivity::class.java).also {
it.putExtra(SampleViewModel::text, "sample")
}
}
}
SavedStateHandle の拡張関数を Delegated Property で使い、値や LiveData を取得できます。初期値の設定や SavedStateAdapter で任意の型変換ができます。
class SampleViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
val text: String by savedStateHandle.property()
val count: MutableLiveData<Int> by savedStateHandle.liveData(initialValue = 0)
val timeUnit: MutableLiveData<TimeUnit?> by savedStateHandle.liveData(object : SavedStateAdapter<TimeUnit?, Int?> {
override fun toSavedState(value: TimeUnit?): Int? = value?.ordinal
override fun fromSavedState(state: Int?): TimeUnit? = state?.let { TimeUnit.values()[it] }
})
}