何が起きたか
タイトルのままですが。
詳細は省きますが、ListViewの中に動的に画像を表示し、その画像をタップするとカルーセル表示する・・・みたいな処理を実装していました。Twitter(現X)とかでありそうなやつです。
class SampleListBuilder extends StatelessWidget {
const SampleListBuilder({super.key});
@override
Widget build(BuildContext context) {
final List<String> imageUrlList = ['url1', 'url2', 'url3'];
return ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: imageUrlList.length,
itemBuilder: (BuildContext context, int index) {
return Container(
child: InkWell(
onTap: _pushCarousel(index),
child: Image.network(imageUrlList[index], fit: BoxFit.cover,),
),
);
},
);
}
pushCarousel(context) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CarouselView()),
);
}
}
ビルドすると以下のエラーが発生します。
'!_debugLocked': is not true.
調査
調べてみると、Widgetのビルド中に画面遷移を行おうとしたりすると発生するエラーとのこと。
全く自覚なし。だってタップしたときのイベントで設定しているんだから。(つもり)
イベントの処理を変えてテストしてみます。
...省略
return Container(
child: InkWell(
onTap: test(index), // テスト用メソッドに変更
child: Image.network(imageUrlList[index], fit: BoxFit.cover,),
...省略
test(index) {
debugPrint('on tap! ' + index.toString());
}
}
これで一応ビルドは出来るようになりましたが、ビルドしただけなのにコンソールにタップされたよ!のログが並びます。
解決
結論、書き方が悪かったです。
onTap: メソッド(),
だとメソッドの戻り値をonTapイベントにセットするような動きをするのだそうです。
onTap: () => test(index),
とするのが正解でした。
または、画面遷移したいのであればちゃんとメソッドに型を指定すれば"void型は設定できないよ"と教えてくれるので気づけたかもしれません。
うーん、不幸が重なった感じ・・・
調べても全然出てこなかったのはあまりに常識的過ぎてこんなミスをする人がいなかったからなのでしょうか。
誰かの助けになれば幸いです。
修正後サンプル
class SampleListBuilder extends StatelessWidget {
const SampleListBuilder({super.key});
@override
Widget build(BuildContext context) {
final List<String> imageUrlList = ['url1', 'url2', 'url3'];
return ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: imageUrlList.length,
itemBuilder: (BuildContext context, int index) {
return Container(
child: InkWell(
// ①ラムダ式を使う
onTap: () => _pushCarousel(index),
child: Image.network(imageUrlList[index], fit: BoxFit.cover,),
),
);
},
);
}
// ②返却型は書いたほうが自分のためになる
void pushCarousel(context) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CarouselView()),
);
}
}