Android における View にまつわる状態とライフサイクルについての考慮のメモ
Activity が再生成される際の、View の onSaveInstanceState
メソッドと onRestoreInstanceState
メソッドについて個人用にまとめておく。
Activity の再生成
- Activity が再生成 (re-creation) される際には、以前の状態が
Activity#onCreate
とActivity#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
より)
- 『This method is called after
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)
.』
- 『The default implementation of this method performs a restore of any view state that had previously been frozen by
Window
あたりがルートビューのView#saveHierarchyState
やView#restoreHierarchyState
などを呼んで、そっからView#dispatchSaveInstanceState
やView#dispatchRestoreInstanceState
やらが呼ばれて、最後にView#onSaveInstanceState
やView#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 も入力内容がない場合の状態になってて、onRestoreInstanceState
でEditText
の状態が復元される際にTextWatcher
でイベントを捕捉して Presentation Model 側の状態も変える、みたいな。
- 具体的に言うと、例えば
- カスタム View を作って、その内部に状態を持たせる。 状態の保存はカスタム View の
- Android フレームワークの挙動をちゃんと理解しておけばなんとでもなるのだけど、ちゃんとりかいしておかないと変なところでハマる。
- 個人的には Activity と View を疎に保ちたいのだけど、Android フレームワーク的には結構べったりくっついてるので辛い。