ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Android における View にまつわる状態とライフサイクルについての考慮のメモ

Activity が再生成される際の、View の onSaveInstanceState メソッドと onRestoreInstanceState メソッドについて個人用にまとめておく。

Activity の再生成

  • Activity が再生成 (re-creation) される際には、以前の状態が Activity#onCreateActivity#onRestoreInstanceState に渡される。
  • Activity#onRestoreInstanceState が呼ばれるのは、Activity#onStart が呼ばれた後。
    • 『This method is called after onStart() when the activity is being re-initialized from a previously saved state, given here in savedInstanceState.』 (Activity#onRestoreInstanceState より)
  • Activity#onRestoreInstanceState が呼ばれるのは、Activity 再生成後の最初の Activity#onStart が呼ばれた後の 1 回だけ。 (Android 8.0 の端末で実際の挙動を確認。)

View 周り

  • View にも View#onRestoreInstanceState メソッドView#onSaveInstanceState メソッドがあるが、これらはどこから呼ばれるのか?
  • Activity#onRestoreInstanceState メソッドや Activity#onSaveInstanceState メソッドのデフォルト実装による。
    • 『The default implementation of this method performs a restore of any view state that had previously been frozen by onSaveInstanceState(Bundle).』
  • Window あたりがルートビューの View#saveHierarchyStateView#restoreHierarchyState などを呼んで、そっから View#dispatchSaveInstanceStateView#dispatchRestoreInstanceState やらが呼ばれて、最後に View#onSaveInstanceStateView#onRestoreInsntaceState やらにたどり着く。
    • android:saveEnabled の考慮は View#dispatchSaveInstanceState で行われる。
    • 子 View の View#dispatchSaveInstanceState を呼ぶのは ViewGroup#dispatchSaveInstanceState が行っている。
    • ここら辺は実際のコードをみて確認した。 API Level 27。

View にまつわる状態とライフサイクルについての考慮 (?)

  • View Model やら Presenter みたいな、いわゆる Presentation Model 的なものを作っていると、Activity の再生成時の View の状態 (View#onRestoreInstanceState で復元されるやつ) と、Presentation Model 側の状態の同期をどうとるかで悩むことになりがち。
  • 道はいくつもある
    • カスタム View を作って、その内部に状態を持たせる。 状態の保存はカスタム View の View#onSaveInstanceState に任せる。
    • View の状態管理は完全にアプリケーション側の責務ということにして、Android フレームワークの力には頼らない。 View には android:saveEnabled="false" を設定する。
    • Activity 再生成時の状態復元は View だけでやって、Presentation Model 側では View 側の状態復元をフックにして状態を変える。
      • 具体的に言うと、例えば EditText の入力内容に対応して Presentation Model 側で状態を保持する設計を考える。 Activity 再生成時の初期状態では EditText も Presentation Model も入力内容がない場合の状態になってて、onRestoreInstanceStateEditText の状態が復元される際に TextWatcher でイベントを捕捉して Presentation Model 側の状態も変える、みたいな。
  • Android フレームワークの挙動をちゃんと理解しておけばなんとでもなるのだけど、ちゃんとりかいしておかないと変なところでハマる。
  • 個人的には Activity と View を疎に保ちたいのだけど、Android フレームワーク的には結構べったりくっついてるので辛い。