前人未踏の領域へ アプリ開発編

Android, iOSアプリ開発に関する調査メモ置き場。ほとんどAndroid。古い記事にはアプリ以外も含まれます。

Android: ViewModelのSavedStateHandleについて

課題

ViewModelのSavedStateHandleの特性について知りたい

結論

  • SavedStateHandleはプロセスがKillされた場合に状態が保持される
  • アプリを正常終了した場合は状態がクリアされる
  • SharedPreferenceの代替とはならない

調査

ViewModelの作成

まずViewModelを作る。 SavedStateHandleAndroidViewModelの場合に効力を発揮するため、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と組み合わせて使うのが良さそう。