Androidアプリの通信処理はViewModelと状態管理で分離すべき?画面回転や再生成に強い設計方法を解説

Android開発

Androidアプリでネットワーク通信を行う場合、取得中に画面回転が発生したり、バックグラウンド復帰時にActivityやFragmentが再生成されたりするケースがあります。その際、画面側に通信処理を直接書いていると、データ消失や二重通信、UI更新エラーなどの問題が発生しやすくなります。この記事では、Androidアプリで安全に通信結果をUIへ反映するために、ViewModelと状態管理を分離する設計方法について解説します。

ActivityやFragmentに通信処理を書く問題点

Android開発では、最初の段階ではActivityやFragment内でAPI通信を実装することがあります。しかし、アプリが大きくなるにつれて、この方法にはいくつかの問題が発生します。

例えば、ユーザーが画面を横向きに回転すると、Activityは一度破棄されて再生成されます。そのタイミングで通信処理の途中状態や取得済みデータが失われる可能性があります。

また、画面表示の責務とデータ取得処理が同じ場所に存在すると、コードの修正やテストが難しくなります。

問題 原因
回転後にデータが消える ActivityやFragmentが再生成されるため
通信処理が複雑になる UI処理とデータ処理が混在するため
テストしづらい 画面クラスに依存した処理になるため

ViewModelを利用するメリット

AndroidのViewModelは、UIコンポーネントとデータ処理を分離するための仕組みです。

ActivityやFragmentは画面表示だけを担当し、ViewModelがデータ取得や状態保持を担当することで、画面の再生成に強い構造になります。

例えば、ユーザー情報を取得するアプリの場合、以下のような役割分担になります。

  • Activity・Fragment:画面表示、ユーザー操作受付
  • ViewModel:通信開始、状態管理、データ保持
  • Repository:APIやデータベースとの連携

この構成では画面が作り直されてもViewModelが保持しているデータを再利用できるため、不要な再通信を防ぐことができます。

通信結果は状態として管理する

ネットワーク通信を扱う場合、単純に取得したデータだけを保持するのではなく、現在の状態を管理する設計が重要です。

例えば、通信処理では以下のような状態を用意します。

  • Loading:通信中
  • Success:取得成功
  • Error:取得失敗
  • Empty:データなし

このような状態管理を行うことで、UI側は現在の状態に応じて表示を切り替えるだけになります。

例えば、APIから商品一覧を取得する場合、ViewModelは「読み込み中」「商品一覧取得済み」「エラー発生」という状態を保持し、Fragmentはその状態を監視して画面を更新します。

LiveDataやStateFlowでUIへ安全に通知する

ViewModelからUIへデータを渡す方法として、LiveDataやStateFlowが利用されます。

これらを利用すると、ActivityやFragmentのライフサイクルに合わせてデータ通知を制御できます。

例えばStateFlowを利用した場合、以下のような流れになります。

  1. ViewModelがAPI通信を開始する
  2. 取得状態をLoadingへ変更する
  3. 通信成功後にSuccess状態へ変更する
  4. Fragmentが状態変化を検知して画面更新する

UI側が通信処理を直接管理しないため、画面回転後でも最新状態を安全に表示できます。

Repositoryを挟んだ設計がさらに安全

実際のアプリ開発では、ViewModelから直接APIクライアントを呼び出すより、Repository層を用意する設計が一般的です。

Repositoryはデータ取得元を隠蔽する役割を持ちます。

役割
UI 表示とユーザー操作
ViewModel 画面用データ管理
Repository データ取得ルール管理
API・DB 実際のデータ保存場所

例えば、現在はネットワークAPIから取得しているデータでも、将来的にキャッシュやローカルDBを追加する場合、RepositoryがあることでViewModel側の変更を最小限にできます。

画面回転やプロセス再生成への対応方法

ViewModelは画面回転によるActivityやFragmentの再生成には対応できますが、アプリプロセス自体が完全に終了した場合はデータを保持できません。

そのような場合にはSavedStateHandleやRoomなどの永続化技術を組み合わせます。

例えば検索条件やユーザー設定などはSavedStateHandleへ保存し、大量データや履歴情報はRoomデータベースへ保存するといった使い分けができます。

避けたい通信処理の実装例

以下のような実装は、小規模アプリでは動作しても長期的には問題になりやすいです。

  • Fragment内で直接APIを呼び出す
  • 通信完了時に直接Viewを更新する
  • Activity変数に取得結果を保存する
  • 画面破棄後の非同期処理を考慮しない

例えば通信中にユーザーが画面を閉じた場合、存在しないViewへアクセスしてクラッシュする可能性があります。

ViewModelと状態管理を利用すると、このようなライフサイクル問題を避けやすくなります。

まとめ:Android通信処理はViewModelと状態管理を分離する設計がおすすめ

Androidアプリでネットワーク通信結果を安全にUIへ反映するには、ActivityやFragmentに通信処理を集中させるより、ViewModel、Repository、状態管理を分離した設計が適しています。

特に画面回転やプロセス再生成が発生するスマートフォン環境では、UIとデータ処理を分離することで安定した動作を実現できます。

小規模なアプリでも最初から状態管理を意識した設計にしておくことで、機能追加や保守が容易になり、将来的なアプリ拡張にも対応しやすくなります。

コメント

タイトルとURLをコピーしました