Googleによって開発されたフリーかつオープンソースのモバイルアプリケーションフレームワークであるFlutterを用いてTodoアプリを作成してみました。
※Kotlin版はこちら
完成形は以下です。
全ソースコードはこちら
またTodoアプリを題材に、KotlinとFlutterの比較記事も書いています。
アーキテクチャ概要
ざっくりとした全体像です。
一覧画面(main.dart)と詳細画面(TodoItemDetailPage)に2画面構成で、画面遷移自体もNavigator.push()とpop()でそのまま行います。
画面はどちらもStatelessWidgetで実装し、それぞれのModel(MVVMで言うところのViewModel)に持たせます。
また、RealmのFlutterプラグインがあまり使えなかったので、SQLiteを使いました。
pubspec.yaml抜粋
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.0
provider: ^4.3.2+2
sqflite: ^1.3.2+1
shared_preferences: ^0.5.12+4
メイン画面
ChangeNotifierProvider<MainModel>を返却するようにし、MainModelはChangeNotifierを継承します。
これでConsumer<MainMode>内でMainModelが使えるようになります。
中身はListViewでMainModelのリストをListTileにmapして表示しているだけです。
Modelでは上述の通り、ChangeNotifierを継承して実装します。これで、メソッド内で非同期処理が走っても、await で待った後にnotifyListener()とすると、勝手に再描画してくれます。
DBへの実際の処理はTodoItemRepositoryに記載し、ここではそれを呼び出すだけとしています。
詳細画面
特筆すべきことはあまりありませんが、コード量が少ないこともあって、ボタンを押したときの例外処理もここでしてしまっています。
それでも改行しまくっても全体のコードは100行以下です。
詳細ページは更新処理と新規作成両方で使っているので、addメソッドとupdateメソッドを定義しています。
空で渡ってきたりnullで渡ってきたときの分岐を書いているくらいで、ほとんどはTodoItemRepositoryにDBのクエリを記載しています。
SQLite周り
まずDatabaseProviderというクラスをシングルトンで定義します。
こうすることで、初めてDatabaseProviderにアクセスしたときだけinitDatabase()を実行し、次からは同じインスタンスを見るようになります。
次に、Entityを用意します。ここではTodoItemという名前で以下のフィールドを定義しました。
フィールドとgetter定義の他に、SQLiteとのやり取りのためにtoMapとfromMapを定義しています。
DBから渡ってくるのはjsonなので、変換してやる必要があります。
そして、これらを使うためのRepositoryクラスを用意します。
一部しか載せていませんが、insertやdeleteは用意されているものの、rawQueryを書いてSELECTしています。
Realmよりも若干めんどくさいイメージです。
おまけ(完了済みアイテムの表示/非表示切替)
また、Kotlin版の方では実装していませんが、あまりにもFultterが簡単すぎるので、完了済みのアイテムの表示/非表示を切り替えれるようにしました。
SharedPreferenceを使えるようなので、ProviderクラスとしてPersistenceStorageProviderクラスを用意してシングルトンでSharedPreferenceを準備し、StorageRepositoryクラスを各modelから呼んでいます。
まとめ
FlutterのProviderパターンは状態管理が非常にすっきりして、何よりこれでAndroidとiOS両方実装できるので開発スピードが非常に速そうな印象です。
SQLiteはRealmと比べると少し冗長な気がしますが、ローカルDBを使うより、FirebaseなどのmBaaSを使うことの方が多いかと思いますので、あまり欠点とも言えなさそうです。
- 全コードはこちら
参考:
コメント