FutureBuilderを使って非同期にデータ表示 -ひとりアドベントカレンダー Flutter編 2018 その6-
最近のアプリは外部APIやクラウドデータを利用することが多いと思います。そんなとき同期処理をしててはUIにロックが掛かってしまいますので、非同期で処理をする必要があります。
ということで、6日目はFutureBuilderを使ったWidgetの非同期組み立てをやってみます。
昨日までの内容と今後については目次を参照してください。
FutureBuilderを利用する前にFlutter(Dart)のFutureを少し理解する必要がありますが、JavaScriptで言えばPromiseみたいなものと考えればよいかと思います。
「flutter future」でググると資料が沢山見つかりますので詳細はそちらへ譲りますが、簡単に言うと以下の2つの機能からなっています。
クロージャーを利用
非同期なメソッドにはおなじみの「then」メソッドが自動で付きますので、以下のように書けます。遅延処理として見慣れた感じです。
http.get("http://example.com").then((res) {
print(res);
});
async/awaitを作成
クロージャーを利用する他に、async/awaitを利用して非同期処理を実行させることが出来ます。
var res = await http.get("http://example.com");
print(res;
こうすることで変数「res」には同期的に値が入りますので、クロージャーのときとは違ってネストが深くならないというメリットがあります。
この非同期処理をUIにうまく反映させてくれるWidgetが、FutureBuilderになります。
6回目にしてやっとプログラムらしくコードも長くなって来ましたので、GitHubへプロジェクトを準備しました。
日にち単位でブランチを切ってますので、今回はChapter6も参照してください。
FutureBuilderの簡単な利用方法は以下のとおりです(実際の利用例はGitHubを参照してください)。
FutureBuilder(
future: http.get("http://example.com"),
builder: (context, future) {
if (!future.hasData) {
return Center(child: CircularProgressIndicator());
}
return Container(Text(future.data.body));
},
},
ButureBuilderにはfutureとbuilderの2つの引数を渡します。
1つ目のfutureにはFutureを返す非同期関数を指定します。2つ目のbuilderでは取得したデータを利用して表示させるWidgetを指定します。
非同期処理の内容によっては、データの取得に時間がかかる場合があります。取得したデータがリストだったりする場合はアイテム数を0という扱いでなにも表示しないというやり方もありますが、処理中はプログレス表示をしたいところです。
そこで、今回は非同期処理が完了したかどうかをBool型のfuture.hasDataで取得し、CircularProgressIndicatorを表示させてみました。
取得したデータは正規表現で処理していますが、前回やった内容ですので省略します。配列データなのになんでキーつけてるの?って思われるかもしれませんが、今後使う予定です。
さて、今回の実装ではこんな画面になりました。見た目はほとんど変わっていませんが(今回はAndroidなので変わってるって言えば変わってる)、ちゃんとアイコン数が増えてることがわかります。
非同期に取得したデータ表示と、取得中のプログレス表示が簡単に出来るFutureBuilderはなかなか便利です。ですが簡単に利用できてしまうので、今回みたいにUI部分のWidget内にロジックを書いてしまうと全体の見通しが悪くなってしまうのでおすすめしません。
ということで、次回はモデルとビューの分離を考えてみたいと思います。
・・・
案の定アップが遅れ気味ですが、なんとか盛り返していきたいところです。
noteのいいねとかTwitterのフォローとかでケツを叩いてください。