開発
AndroidにおけるMVC
Taro Aoki
こんにちは、アルバイトの青木です。
最近、Androidアプリの開発をしていてAndroidにおけるMVCの実現がなんか少し分かりづらいなと感じました。
今回はある程度まとめたものを記事として公開したいと思います。なお、未熟な部分があるかと思いますので、指摘していただけると幸いです。
MVCとは
MVCはモデル・ビュー・コントローラの略で、ソフトウェア設計手法の1つです。
ソフトウェアを機能に従ってこの3つの種類に分けていきます。
モデルでは実際のバックエンドの処理を行い、ビューではデータの表示を行い、コントローラではそれらの仲介を主に行っています。
Androidのライフサイクル
AndroidやiPhoneなどのモバイル端末にはたくさんのアプリケーションがインストールされていて、アプリAを呼び出すと現在表示されているアプリがバックグラウンドに移動します。
また、画面の表示はActivityやFragmentというが行っています。違いについては今回は省略します。
iPhoneは詳しくないのでわからないのですが、Activityは図の様なライフサイクルをとっています。
アプリがバックグラウンドへ移動するとonPause()が呼ばれます。それから再び表示されるまで何も行われませんが、メモリが少なくなるとシステムからkillされることがあります。そうすると、復帰した時に再びonCreate()が呼ばれ、再生成されることになります。なのでActivityでバックグラウンドの処理などまで行ってしまうと再生成時にリセットされ、クラッシュします。
ゆえにMVCに分けることはアプリのクラッシュを防ぐ役割も果たしています。
AndroidにおけるMVC
AndroidではビューはActivityやFragmentが担当しています。コントローラ的な部分もありますが、自分は極力コントローラ的な役割はさせないようにしています。
考え方は色々あるのですが、自分は以下の様な構成にしています。
コントローラではUseCaseという名前のクラスを作成し、ここから色々なデータを要求します。モデルではLogicというクラスを作成し、外部と通信を行ってデータを取得などの実際の処理を行います。例えばFragmentからUseCaseへある音ゲーの楽曲のリストを要求したとします。UseCaseはデータベースを検索し、見つかればそれを返します。しかしデータベースになかった場合、UseCaseはLogicのインスタンスを生成し、データを取ってくる処理を行います。Logicからデータが返されたらそれをそのままFragmentへ渡します。
ライブラリ
基本は上の通りですが、これを実装しようとすると意外と面倒です。例えばhttpでデータを取得したい場合、AndroidではMainThreadからネットワーク通信を行ってはいけないという制約があり、その解決策としてAsyncTaskというものを利用しなければいけません。
問題はこれで解決しますが、非同期処理を順番に行いたい時はAsyncTaskを入れ子にしなければいけなく、非常にコードが多く、見づらくなってしまいます。
このように標準のものだけでの実装は何かと大変です。なのでライブラリをいくつか利用しています。
- Butter Knife
- データのバインドを簡単にするライブラリ
- jdeferred
- Promiseのように非同期処理を書けるライブラリ
- OkHttp
- http通信を簡単に書けるライブラリ
- Stetho
- 通信のログやデータベースの中身を見ることのできるライブラリ
- EventBus
- UseCaseからFragmentへ値を返すときに通知で返せるようにできるライブラリ
- Realm
- 高速かつ簡単に動作するNoSQLデータベース。
- Jsonの変換までしてくれる
特にUseCaseからViewへデータを渡すときに、Viewが破棄されている可能性があるので、普通に返すとクラッシュするときがあります。
しかし、EventBusで通知として渡せば、破棄されていても落ちることはありません。
これらの関係を図に表すと以下のようになります。
これから何か問題が発生する可能性はなんともいえませんが、少なくとも今現在は何も問題は起きていなく快適です。
参考