fluxとかMVIみたいな構造のアプリを作ってみたかった その3
つづきです akihito104.hatenablog.com
- 今:Eventを流してModelを更新し、その結果ViewStateが更新される
- 課題:Modelを更新したときに出てくる例外をどうするか
例えばこんな感じのハッピーパスしか考えてないやつ(スレッドとか中断関数とかそういうことは端折っています):
val state: LiveData<State> = updateEventFlowable .map { event -> model.update(event.text) } .toLiveData()
model.update()で例外が起きるとLiveDataでは例外を処理できない的なメッセージが出てクラッシュする。こういうケースでどうするか考えていく。
- 想定される例外(IOExceptionとかAPI limit exceeded的なやつ)が起きたときはリカバリしたい
- リカバリは今のところやり直すとかいうよりは「だめだったからあとでやり直してね」ってToastとかSnackbarとかでユーザーに伝えるぐらいしかない
- 想定外の例外が起きてリカバリできない(どうするのが正しいのか分からない)時はちゃんと大域脱出(クラッシュ)したい
- テストの文脈(mockkとか)で出てくるような例外を握りつぶさないように
- でも例えばFragmentスコープでは解決できなくてもActivityスコープとかApplicationスコープでなら解決できるならそのスコープでキャッチしてリカバリしてもいいと思う
Event -> (Model) -> ViewState
という流れとは別に、 Event -> (Model) -> 例えばMessage
のような終端も必要ということかなと考えて、
- Eventを流してModelを更新し、その結果をResultという形で得る
- ResultからViewStateを得る、もしくはResultから例外を得てリカバリする
のような感じで、間にもう1クッション挟んで分岐できるようにしたらいいのだろうか。だんだん巨大になっていくのでもっといい抽象化の仕方があるのではないかという気がする。結論は出ていないけどとりあえずその方向で実装して動きを見てみようと思う。
あとは、RepositoryからLiveDataを返すような関数を生やしていたけど、上のようなことを考慮するにあたってLiveDataを返すようなのはこのケースには合わないのかなと思い始めている。この辺はまだもやもやしていてうまく説明できない。でもRepositoryのコードがViewStatesにどんどん移動していくことになりそう。