这主要是为了讨论,但真的.
我还没有在互联网上找到类似的东西,所以我想也许有一些性能上的冲击,或者可能没有人没有try 过.但如果不是这样,这个构造函数将非常有助于减少ListView
的样板代码.
通常情况下,当我们使用ListView.builder()
构造函数时,它看起来如下所示:
@override
Widget build(BuildContext context) {
final items = <ListItem>[
// item 1,
// item 2,
// ... et cetera
];
// ... code
child: ListView.builder(
itemBuilder: (context, index) => SomeFancyListTile(
leading: Image.network(items[index].imageUrl),
title: Text(items[index].title),
),
itemCount: items.length,
),
// ... more code
}
这完全没问题,但最近我需要用LinkedList
来修改基于相邻元素的Widget,它没有方便的[]
运算符,而只有.elementAt(index)
个方法.然而,知道LinkedList
是如何构造的,对于大型列表,代码将非常不优化(呈现整个列表需要O(n^2)).
但后来我想,并不需要这样,因为ListView
会一个接一个地呈现项目,这正是迭代器的工作方式.
所以,我实现了一个定制的SliverChildDelegate
,它正好做到了这一点-结合了迭代器的功能和ListView
‘S渲染.它还带来了一些语法改进,减少了每次需要访问列表项时的样板代码和items[index]
的使用.
import 'package:flutter/material.dart';
typedef ValueWidgetBuilder<T> = Widget Function(BuildContext context, T value);
class SliverIterableBuilderDelegate<T> extends SliverChildDelegate {
SliverIterableBuilderDelegate(
this.iterable, {
required this.builder,
}) : iterator = iterable.iterator;
final Iterable<T> iterable;
final ValueWidgetBuilder<T> builder;
final Iterator<T> iterator;
@override
Widget? build(BuildContext context, int index) {
if (index < 0 || index >= iterable.length) {
return null;
}
if (iterator.moveNext()) {
return builder(context, iterator.current);
}
return null;
}
@override
bool shouldRebuild(covariant SliverChildDelegate oldDelegate) => true;
}
@override
Widget build(BuildContext context) {
final items = <ListItem>[
// item 1,
// item 2,
// ... et cetera
];
// ... code
child: ListView.custom(
childrenDelegate: SliverIterableBuilderDelegate(
builder: (context, value) => SomeFancyListTile(
leading: Image.network(value.imageUrl),
title: Text(value.title),
),
),
// ... more code
}
所以,我想知道这种方法是否有一些缺点?此外,还建议添加一个ListView.iterable()
构造函数以进一步减少代码.