ListView.builder、ListTile、そして独自のウィジェットに切り出した項目のおかげで、数千個の項目のリストを遅延なく表示しましょう。
このレッスンを Kodokon で開く実際のアプリはほとんどの場合リストを表示します。メッセージ、商品、連絡先などです。すでに知っているListView(children: ...)コンストラクターは、その子ウィジェットをすべて一度に構築します。10個の項目なら問題ありませんが、1000個となると悲惨です。ListView.builderは、スクロールに応じて必要なときに、表示領域の近くにある項目だけを構築します。
import 'package:flutter/material.dart';
class ContactsScreen extends StatelessWidget {
const ContactsScreen({super.key, required this.names});
final List<String> names;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Contacts')),
body: ListView.builder(
itemCount: names.length,
itemBuilder: (context, index) {
return ListTile(
leading: const Icon(Icons.person),
title: Text(names[index]),
);
},
),
);
}
}二つのパラメーターがこの仕組みのすべてを担います。itemCountは項目の総数を宣言し、itemBuilderは指定されたインデックスの項目を、それが画面に近づいたときだけ生成します。各行の中身については、ListTileがあなたのMaterialの味方です。leading、title、subtitle、trailingが行を構造化し、onTapがタッチ時のインクの波紋を提供します。しかし項目が大きくなってきたら、itemBuilderの中で膨れ上がらせてはいけません。独自のウィジェットに切り出しましょう。
import 'package:flutter/material.dart';
class ContactTile extends StatelessWidget {
const ContactTile({
super.key,
required this.name,
required this.onTap,
});
final String name;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return ListTile(
leading: CircleAvatar(child: Text(name[0])),
title: Text(name),
trailing: const Icon(Icons.chevron_right),
onTap: onTap,
);
}
}切り出した項目は、単独でテストでき、他の画面でも再利用でき、itemBuilderをごくシンプルにします。よくある要望がもう一つ残っています。区切り線です。ListView.separatedはbuilderのように動きますが、三つ目のパラメーターseparatorBuilderがあり、各項目の間で呼び出されます。最後の要素のあとに区切り線が置かれることは決してありません。
import 'package:flutter/material.dart';
class ContactList extends StatelessWidget {
const ContactList({super.key, required this.names});
final List<String> names;
@override
Widget build(BuildContext context) {
return ListView.separated(
itemCount: names.length,
separatorBuilder: (context, index) {
return const Divider(height: 1);
},
itemBuilder: (context, index) {
return ContactTile(
name: names[index],
onTap: () => debugPrint(names[index]),
);
},
);
}
}