🗂

hasDataについて

2021/05/18に公開

はじめに

今回はコミュニティ参加者の方から hasData について質問がありましたので、そちらを書いていきます。

質問内容

こちらのソースコードにおける hasData の役割とか動きを知りたいです!
https://flutter.dev/docs/cookbook/networking/fetch-data#why-is-fetchalbum-called-in-initstate

hasData の役割と snapshot.hasData

has の意味は「持っている」かどうかなので、上記はデータを持っているかどうかという意味

snapshot とは

「その時点のものを保存したもの」です。

時間を止めて、その時点のデータをコピーしておくためのもの

その時点のデータをコピーは永久?消えてしまうもの?
→ その関数の中で生き続ける

変数に snapshot のデータ入れておけば、その変数の中でデータは生き続ける
データのリクエストを投げてリクエストが返ってきたときの状態が snapshot

しかし、とってきた後もデータは更新され続けている

  • 関数の中で snapshot をいれたらその関数から抜けるまでは生き続ける
  • 退避していればその変数で使い回しできる

snapshot の概念

トランザクションのような感じ
(トランザクションは、まとめて扱う必要のある複数の一連の処理!)

snapshot 自体がデータだから id がある。同じタイミングで id が衝突する可能性があるため、先に更新がかかったものを更新して、その次のデータは更新できないようにするため

情報のスタックが重なってデッドロック(処理が止まる)がかかる可能性がある

デッドロックとは

例えば 2 つの処理が同時に発生してお互いがもう一方の処理完了を待っている場合、お互いがずっと待ち状態になって処理が進まなくなってしまう状態

hasData を通さないといけない理由

「hasData」と検索すると「非同期」という言葉が出てくるけど、「hasData を通さないといけない理由」には関係がない。

hasData は呼び出し元
(FutureBuilder[StateFullWidget]) -> snapshot[AsyncSnapshot] -> hasData[bool]

コード抜選

child: FutureBuilder<Album>( future: futureAlbum, builder: (context, snapshot) { if (snapshot.hasData) {

hasData のやっていることは null か null じゃないかの判定だけ(つまり異常検知のための hasData)
何かからデータをとってくる場合は hasData を使うことが多い
データが帰ってくる場合もあるし、返ってこない場合もある。もしデータが返ってこなかった場合どうする?ってときに使用する。

もしデータが返ってこなかった場合の処理追加で、hasData が false になるから、false を受け取ったら処理を記載するイメージ。

hasData を一度挟んで、データが null であるかどうかを判別してからじゃないと出力できない

hasData は挟まなくても出力できるけど、null だった場合はアプリが落ちる
try catch みたいなイメージ

snapshot 使用例

if (snapshot.hasData) {
///           children = <Widget>[
///             Icon(
///               Icons.check_circle_outline,
///               color: Colors.green,
///               size: 60,
///             ),
///             Padding(
///               padding: const EdgeInsets.only(top: 16),
///               child: Text('Result: ${snapshot.data}'),
///             )
///           ];
///         } else if (snapshot.hasError) {
///           children = <Widget>[
///             Icon(
///               Icons.error_outline,
///               color: Colors.red,
///               size: 60,
///             ),
///             Padding(
///               padding: const EdgeInsets.only(top: 16),
///               child: Text('Error: ${snapshot.error}'),
///             )
///           ];
///         } else {
///           children = <Widget>[
///             SizedBox(
///               child: CircularProgressIndicator(),
///               width: 60,
///               height: 60,
///             ),
///             const Padding(
///               padding: EdgeInsets.only(top: 16),
///               child: Text('Awaiting result...'),
///             )
///           ];
///         }
637行目

まとめ

  • snapshot.hasData:その時点で保存したデータを持っているかどうかの確認
  • snapshotはその時点のデータをコピーする。変数に snapshot のデータを入れておけば、その関数の中で生き続ける。
  • snapshot はトランザクションのようなもので、snapshot 自体がデータだから id がある。
  • hasData は、何かからデータを取ってくる時の null か null じゃないかの判定をするもの。データがデータが返ってこなかった時の処理を行いたい時に使う。

参考サイト

FutureBuilder https://github.com/flutter/flutter/blob/b21e08c80160e89c800543a4b9990459bc71043d/packages/flutter/lib/src/widgets/async.dart#L685https://github.com/flutter/flutter/blob/b21e08c80160e89c800543a4b9990459bc71043d/packages/flutter/lib/src/widgets/async.dart#L685

snapshot https://github.com/flutter/flutter/blob/b21e08c80160e89c800543a4b9990459bc71043d/packages/flutter/lib/src/widgets/async.dart#L749

hasData(重要) https://github.com/flutter/flutter/blob/b21e08c80160e89c800543a4b9990459bc71043d/packages/flutter/lib/src/widgets/async.dart#L284

Discussion