【Flutter】GridView.builderのitemBuilderでreturn nullできなくて混乱した件
背景
Flutter入門中で、今回GridViewを使って画像の無限スクロールを実装しようとしてました。
今回使用したバージョン
Flutter 3.3.10 • channel stable
TL;DR
- 無限スクロールでトータル件数分からないとき、
GridView
のitemCount
って何設定するんだ? - どうやら
itemCount
指定しなくても、itemBuilder
でreturn null;
すればスクロール止めれるらしい - 実際に
return null;
で試す- エラーわず
- なんで?
- Flutterの過去verでは
return null;
できたらしいが、数年前Flutterのnull-safety対応中にnull許容じゃなくなったらしい(意図的かは私把握できてない) - Issueが建てられてて、2022年9月にnull許容復活(まだmasterにマージのみ)
- でもよくよく考えたら、リスト変わるごとに全体リビルドしてれば、その都度のitemCount指定すれば良かったのでは(今ここ)
最初の思考
- Grid表示できるウィジェットあるかな? → GridViewってのがあった
- コンストラクタ複数あるけど、画面に表示してる範囲(と前後いくつか)のみレンダリングできる
GridView.builder
が無限スクロールに適してそう → これ使お。 - 引数に
itemCount
渡すとそこでスクロール終わらせられるらしい - リスト返してる今のAPIじゃトータル件数分かんないどうしよ。。
- どうやら
itemCount
指定しなくても、itemBuilder
でreturn null;
すれば良さそう。実際return null;
してる記事も発見。これでいこう
It is legal for itemBuilder to return null. If it does, the scroll view will stop calling itemBuilder, even if it has yet to reach itemCount.
Google翻訳
itemBuilder が null を返すことは正当です。その場合、たとえ itemCount に達していなくても、スクロール ビューは itemBuilder の呼び出しを停止します。
- 書いてみた
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
// no itemCount
itemBuilder: ((context, index) {
if (index == photos.length) {
// 次のページ読み込み
fetchPhotos();
return const CircularProgressIndicator();
} else if (index > photos.length) {
// スクロール終了
return null; // <- これ
}
return Image.network(photos[index].url);
}),
),
),
);
}
- なんかエラー出てる。なんだ?
The return type 'Null' isn't a 'Widget', as required by the closure's context.
Issueあった
どうやらFlutterの過去verではreturn null;
できたが、NNBDというnull-safety関連の対応中にitemBuilder
が求める型がnull許容じゃなくなったらしい。(IndexedWidgetBuilder
型になってた)
で、↓のIssueで議論して頂いてて、結局2022年9月にnull許容復活した模様(まだmasterにマージのみ)。元々の変更が意図的なものだったかは詳細分からなかった。(読解力ないだけかも)
Issue
対応PRでも結局・・・?
リスト変わるごとに全体リビルドしてれば、その都度のitemCount指定すれば良かったのでは(今ここ)。動かしてみた感じ今のとこ問題なさそうだけど、まだFlutterのレンダリングの仕組みやパフォーマンス周り理解できてないのでこの辺の勉強しなきゃいけない。
さいごに
Flutterの公式ドキュメントがどのリリースバージョン指してるのかとか、そもそもFlutterのリリースフロー周りも理解できてないので、この辺も勉強しとかなきゃっていう良い機会になった。
masterにマージされたものは4ヶ月に1回のペースでstableブランチとなってstable版リリースされるってこと?
Discussion