課題
ViewModelのSavedStateHandleの特性について知りたい
結論
- SavedStateHandleはプロセスがKillされた場合に状態が保持される
- アプリを正常終了した場合は状態がクリアされる
- SharedPreferenceの代替とはならない
調査
ViewModelの作成
まずViewModelを作る。
SavedStateHandle
はAndroidViewModel
の場合に効力を発揮するため、AndroidViewModel
を継承する。
class UserViewModel(application: Application) : AndroidViewModel(application) {
}
次にSavedStateHandle
をコンストラクタで受け取るために追加する
class UserViewModel(application: Application,
private val state: SavedStateHandle) : AndroidViewModel(application) {
}
name
プロパティをLiveDataで追加。この際、state
から値を取得、セットする。
class UserViewModel(
application: Application,
private val state: SavedStateHandle
) : AndroidViewModel(application) {
val name: MutableLiveData<String> by lazy {
state.getLiveData("NAME", "")
}
fun saveName(name: String) {
state.set("NAME", name)
}
}
Fragmentから値をセットする
お試しなので、ある画面のonResumeで値をセットしてみよう。
class HogeFragment : Fragment() {
private val userViewModel: UserViewModel by activityViewModels()
override fun onResume() {
super.onResume()
userViewModel.saveName("SUCCESS!")
}
}
Fragmentから値を取得する
そしてまたある画面のonResume()で値を取得し、ログに出力してみる
class UserFragment : Fragment() {
private val userViewModel: UserViewModel by activityViewModels()
override fun onResume() {
super.onResume()
Log.d("SavedStateHandleテスト", "出力:${userViewModel.name.value}")
}
}
実験
最初にUserFragmentにアクセスすると以下が表示される。値は空だ。
D/SavedStateHandleテスト: 出力:
次に HogeFragmentにアクセス、UserFragmentに戻ると以下が表示される
D/SavedStateHandleテスト: 出力:SUCCESS!
ここで一度ホームボタンを押してホームに戻り、AndroidStudioのLogCatビューからアプリを強制終了(Terminate Application)し、プロセスをKillする。
そしてアプリを再度立ち上げ、UserFragmentに遷移すると値が保持されていることが分かる。
D/SavedStateHandleテスト: 出力:SUCCESS!
次にアプリをバックボタンや最近使ったアプリ上からスワイプするなどして終了させてから
アプリを立ち上げて確認すると.....
D/SavedStateHandleテスト: 出力:
値がクリアされている。
ということでonSavedInstanceStateと同じようなイメージで使用しよう。
といいうつつ普段savedInstanceStateほとんど使ってないんだけど...
ログイン情報などSharedPreferenceに持たせていた情報はこれまで通りSharedPreferenceに持ちつつViewModelと組み合わせて使うのが良さそう。