Списки — один из самых важных компонентов в мобильных приложениях. В этой статье разберём как работать с большими списками во Flutter без потери производительности.
Проблема больших списков
Неправильная реализация списка из 10000 элементов может: — Убить приложение с OutOfMemory — Сделать UI медленным — Потреблять много батареи
ListView.builder
Правильный способ для динамических списков:
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(title: Text(items[index]));
},
)
Почему это быстро? — Строит только видимые элементы — Переиспользует виджеты — Автоматически кеширует
ListView.separated
ListView.separated(
itemCount: items.length,
separatorBuilder: (context, index) => Divider(),
itemBuilder: (context, index) {
return ListTile(title: Text(items[index]));
},
)
SliverListView для CustomScrollView
CustomScrollView(
slivers: [
SliverAppBar(
title: Text('Sliver List'),
),
SliverList(
delegate: SliverChildBuilderDelegate(
childCount: items.length,
builder: (context, index) {
return ListTile(title: Text(items[index]));
},
),
),
],
)
Lazy loading
class _MyHomePageState extends State<MyHomePage> {
final List<Item> items = [];
final ScrollController _controller = ScrollController();
bool _isLoading = false;
@override
void initState() {
super.initState();
_loadMore();
_controller.addListener(_scrollListener);
}
void _scrollListener() {
if (_controller.position.pixels >=
_controller.position.maxScrollExtent - 200) {
_loadMore();
}
}
Future<void> _loadMore() async {
if (_isLoading) return;
setState(() => _isLoading = true);
final newItems = await api.fetch(offset: items.length);
setState(() {
items.addAll(newItems);
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
return ListView.builder(
controller: _controller,
itemCount: items.length + (_isLoading ? 1 : 0),
itemBuilder: (context, index) {
if (index == items.length) {
return Center(child: CircularProgressIndicator());
}
return ListTile(title: Text(items[index].title));
},
);
}
}
Optimised ListTile
// Используйте const конструкторы
const ListTile(
leading: Icon(Icons.person),
title: Text('Title'),
trailing: Icon(Icons.arrow_forward),
)
Заключение
Для больших списков используйте ListView.builder или SliverListView с lazy loading. Избегайте ListView с большим количеством детей.