モデル化させてMとVを分離 -ひとりアドベントカレンダー Flutter編 2018 その7-
Flutterではロジック部分もUI部分もDartで書くことが出来ることがメリットなのですが、ロジックとUIが混じってしまうと見通しが非常に悪くなり保守性が低くなります。
ということで、7日目は前回のコードをリファクタリングしてモデル化させてみます。
昨日までの内容と今後については目次を参照してください。
リファクタリングしてモデル化といっても、FlutterだからとかDartだからとか特別な話は殆どありません。今回はモデルとしてIconクラスとIconsクラスを作ってデータの取得をモデルに持っていっただけです。
実際のコードはGitHubプロジェクトのChapter7ブランチを参照ください。
説明を付け加える必要もないくらい単純なコードですが、ポイントはFutureを返すメソッドを準備するところですかね。
class MIcons {
List<MIcon> items = [];
Future<List<MIcon>> fetchIcons() async {
String url = "http://example.com";
http.Response res = await http.get(url);
...
return this.items;
}
}
戻り値の型の Future とメソッド名後の async は対で使い、この形になっているメソッドは await を挟んで同期的にも使えるし、 then を使った非同期な使い方もできるようになります。
また、メソッド内で await を利用する場合はそのメソッドで async 宣言されている必要があります。
上の使用例ではなかなか分かりづらいのですが、GitHubにアップしている実際の使用例ではネストも必要なく非常にわかりやすく書けるのがわかると思います。
モデルを上記のように準備したら、実際のコードでは
FutureBuilder(
future: MIcons().fetchIcons(),
builder: (context, future) {
if (!future.hasData) {
return Center(child: CircularProgressIndicator());
}
List<MIcon> icons = future.data;
return GridView.builder(
temCount: icons.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
),
itemBuilder: (context, index) {
return Card(
child: Icon(icons[index].iconData, size: 50),
);
},
);
},
),
のように使えます。
どうでしょう?前回のコードと比べてUI部分の記述だけになったので非常にわかりやすくなってると思います。
今まではモデル(M), ビュー(V), コントローラー(C)と分けるのが一般的だったと思いますが、FlutterではMVだけで十分なケースがほとんどです。
というのも、「FutureBuilderという標準で備わってるWidgetでモデルに命令を出せる」からです。
(ここらへんはあまり詳しくないので、素人が勝手に感じてるところです)
というところで、今回は終わりです。Dartの設計思想もあり、Flutterではかなり柔軟なモデル化が出来ます。
今回は説明できていませんが、コンストラクタの指定が柔軟なのでなかなかおもしろいです。時間があればどこかで紹介したいですね。
・・・
案の定アップが遅れ気味ですが、なんとか盛り返していきたいところです。
noteのいいねとかTwitterのフォローとかでケツを叩いてください。