迭代器模式 - Flutter中的集合导航专家,解锁数据遍历的无限可能!
/ 用于排序// 是否异步加载。
·
自定义滚动效果/树形结构遍历/分页加载…用迭代器掌控数据流动的节奏
痛点场景:多源数据混合遍历
假设你的社交应用需要显示以下内容:
- 本地缓存的帖子
- 新收到的实时消息
- 推荐广告
- 朋友动态
这些数据来自不同接口,结构各异:
List<Post> cachedPosts = [...];
Stream<Message> realtimeMessages = [...];
List<Ad> ads = [...];
Future<List<FriendActivity>> friendActivities = [...];
传统遍历方式:
// 需要处理各种数据类型和异步状态
List<Widget> buildFeed() {
final widgets = <Widget>[];
// 添加缓存帖子
widgets.addAll(cachedPosts.map((p) => PostCard(p)));
// 添加广告
widgets.insert(2, AdCard(ads[0]));
// 处理实时消息
if (latestMessage != null) {
widgets.insert(0, MessageBubble(latestMessage));
}
// 异步加载朋友动态
friendActivities.then((activities) {
widgets.addAll(activities.map((a) => ActivityItem(a)));
});
return widgets;
}
问题爆发点:
- 🌀 遍历逻辑分散在各处
- ⏳ 需要手动处理异步数据
- 🔀 插入顺序难以维护
- 📦 新增数据源需要修改核心代码
迭代器模式解决方案
核心思想: 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部表示。
三个关键角色:
- 迭代器接口(Iterator): 定义遍历操作
- 具体迭代器(ConcreteIterator): 实现遍历逻辑
- 可迭代集合(Aggregate): 提供创建迭代器的方法
Flutter混合数据源迭代器实现
1. 定义统一的内容接口
abstract class FeedContent {
Widget buildWidget();
int get priority; // 用于排序
bool get isAsync; // 是否异步加载
}
2. 实现具体内容类
class PostContent implements FeedContent {
final Post post;
Widget buildWidget() => PostCard(post);
int get priority => 1;
bool get isAsync => false;
}
class AdContent implements FeedContent {
final Ad ad;
Widget buildWidget() => AdCard(ad);
int get priority => 3;
bool get isAsync => false;
}
class MessageContent implements FeedContent {
final Message message;
Widget buildWidget() => MessageBubble(message);
int get priority => 0; // 消息置顶
bool get isAsync => true;
}
3. 创建混合迭代器
class FeedIterator implements Iterator<FeedContent> {
final List<Iterator<FeedContent>> _iterators = [];
int _currentIndex = 0;
FeedIterator({
required List<Post> posts,
required List<Ad> ads,
required Stream<Message> messages,
}) {
// 初始化各数据源的迭代器
_iterators.add(posts.map((p) => PostContent(p)).iterator);
_iterators.add(ads.map((a) => AdContent(a)).iterator);
_iterators.add(messages.map((m) => MessageContent(m)).iterator);
// 按优先级排序
_iterators.sort((a, b) => a.current.priority.compareTo(b.current.priority));
}
FeedContent get current => _iterators[_currentIndex].current;
bool moveNext() {
// 先尝试移动当前迭代器
if (_iterators[_currentIndex].moveNext()) {
return true;
}
// 当前迭代器结束,切换到下一个
while (_currentIndex < _iterators.length - 1) {
_currentIndex++;
if (_iterators[_currentIndex].moveNext()) {
return true;
}
}
return false; // 所有迭代器结束
}
}
4. 创建可迭代集合
class FeedCollection implements Iterable<FeedContent> {
final List<Post> posts;
final List<Ad> ads;
final Stream<Message> messages;
FeedCollection({required this.posts, required this.ads, required this.messages});
Iterator<FeedContent> get iterator => FeedIterator(
posts: posts,
ads: ads,
messages: messages,
);
}
5. 在Flutter中使用
class FeedView extends StatefulWidget {
final FeedCollection feedCollection;
_FeedViewState createState() => _FeedViewState();
}
class _FeedViewState extends State<FeedView> {
final List<Widget> _feedWidgets = [];
void initState() {
super.initState();
_loadFeed();
}
Future<void> _loadFeed() async {
for (final content in widget.feedCollection) {
if (content.isAsync) {
// 异步内容稍后加载
content.buildWidget().then((widget) {
setState(() => _feedWidgets.add(widget));
});
} else {
// 同步内容立即添加
setState(() => _feedWidgets.add(content.buildWidget()));
}
}
}
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _feedWidgets.length,
itemBuilder: (ctx, index) => _feedWidgets[index],
);
}
}
Flutter中的实际应用场景
场景1:树形结构遍历
// 树节点迭代器
class TreeNodeIterator implements Iterator<TreeNode> {
final List<TreeNode> _stack = [];
TreeNodeIterator(TreeNode root) {
_stack.add(root);
}
TreeNode get current => _stack.last;
bool moveNext() {
if (_stack.isEmpty) return false;
final node = _stack.removeLast();
// 逆序添加子节点,保证正序访问
for (int i = node.children.length - 1; i >= 0; i--) {
_stack.add(node.children[i]);
}
return _stack.isNotEmpty;
}
}
// 在折叠菜单中使用
ExpandableListView(
iterator: TreeNodeIterator(categoryTree),
builder: (node) => ListTile(
title: Text(node.name),
onTap: () => _handleCategorySelect(node),
),
)
场景2:分页加载列表
// 分页迭代器
class PaginatedIterator<T> implements Iterator<T> {
final Future<List<T>> Function(int page) _fetchPage;
List<T> _currentItems = [];
int _currentIndex = 0;
int _currentPage = 0;
bool _hasMore = true;
T get current => _currentItems[_currentIndex];
Future<bool> moveNext() async {
_currentIndex++;
// 需要加载下一页
if (_currentIndex >= _currentItems.length && _hasMore) {
final newItems = await _fetchPage(_currentPage + 1);
if (newItems.isEmpty) {
_hasMore = false;
return false;
}
_currentItems.addAll(newItems);
_currentPage++;
}
return _currentIndex < _currentItems.length;
}
}
// 使用
final iterator = PaginatedIterator<Post>((page) => api.fetchPosts(page));
while (await iterator.moveNext()) {
final post = iterator.current;
// 处理帖子...
}
场景3:复合图形绘制
// 图形迭代器
class ShapeIterator implements Iterator<Shape> {
final List<Shape> _shapes;
int _index = 0;
Shape get current => _shapes[_index];
bool moveNext() => ++_index < _shapes.length;
}
// 在CustomPainter中使用
void paint(Canvas canvas, Size size) {
final iterator = ShapeIterator(complexShape.components);
while (iterator.moveNext()) {
final shape = iterator.current;
shape.paint(canvas);
}
}
迭代器模式与Flutter状态管理结合
将分页迭代器与Provider结合:
class PaginatedListProvider extends ChangeNotifier {
final PaginatedIterator<Post> _iterator;
final List<Post> _posts = [];
bool _isLoading = false;
PaginatedListProvider(this._iterator);
Future<void> loadMore() async {
if (_isLoading) return;
_isLoading = true;
notifyListeners();
while (await _iterator.moveNext()) {
_posts.add(_iterator.current);
if (_posts.length % 20 == 0) break; // 每页20条
}
_isLoading = false;
notifyListeners();
}
}
// 在ListView中使用
Consumer<PaginatedListProvider>(
builder: (context, provider, child) {
return ListView.builder(
itemCount: provider._posts.length + (provider._isLoading ? 1 : 0),
itemBuilder: (ctx, index) {
if (index == provider._posts.length) {
provider.loadMore();
return LoadingIndicator();
}
return PostItem(provider._posts[index]);
},
);
}
)
迭代器模式最佳实践
-
何时使用迭代器模式:
- 需要统一遍历不同类型的集合
- 需要支持多种遍历方式(正序、逆序、过滤等)
- 不希望暴露集合内部结构
- 需要延迟加载或分页处理大数据集
-
Dart语言特性利用:
// 实现Iterable接口 class MyCollection implements Iterable<Item> { Iterator<Item> get iterator => MyIterator(); // 支持for-in循环 // 支持map/where/expand等集合操作 } // 使用yield实现懒加载 Iterable<Item> getItems() sync* { while (hasMore) { final batch = fetchNextBatch(); for (final item in batch) { yield item; // 逐个产出,避免一次性加载 } } } -
性能优化技巧:
// 懒加载迭代器 class LazyIterator implements Iterator<Item> { Future<List<Item>>? _currentBatch; List<Item> _currentItems = []; int _index = 0; Future<bool> moveNext() async { _index++; if (_index >= _currentItems.length) { _currentBatch ??= _fetchNextBatch(); _currentItems = await _currentBatch!; _currentBatch = null; _index = 0; } return _index < _currentItems.length; } } -
测试策略:
test('树形迭代器应深度优先遍历', () { final root = buildTestTree(); final iterator = TreeNodeIterator(root); final visitedOrder = []; while (iterator.moveNext()) { visitedOrder.add(iterator.current.id); } expect(visitedOrder, equals([1, 2, 3, 4, 5])); // 验证遍历顺序 });
迭代器模式 vs 访问者模式
| 特性 | 迭代器模式 | 访问者模式 |
|---|---|---|
| 目的 | 遍历集合元素 | 对集合元素执行操作 |
| 焦点 | 如何遍历 | 对元素做什么操作 |
| 适用场景 | 统一遍历接口/懒加载 | 添加新操作而不修改元素类 |
| Flutter应用 | 分页加载/复杂结构遍历 | 报表生成/UI渲染器 |
迭代器模式的高级变体
1. 过滤迭代器
class FilteringIterator<T> implements Iterator<T> {
final Iterator<T> _source;
final bool Function(T) _predicate;
T? _current;
FilteringIterator(this._source, this._predicate);
T get current => _current!;
bool moveNext() {
while (_source.moveNext()) {
if (_predicate(_source.current)) {
_current = _source.current;
return true;
}
}
return false;
}
}
// 使用
final numbers = [1, 2, 3, 4, 5].iterator;
final evenNumbers = FilteringIterator(numbers, (n) => n % 2 == 0);
2. 并行迭代器
class ParallelIterator<T> implements Iterator<T> {
final List<Iterator<T>> _iterators;
int _currentIterator = 0;
T get current => _iterators[_currentIterator].current;
bool moveNext() {
if (_iterators[_currentIterator].moveNext()) {
return true;
}
_currentIterator++;
return _currentIterator < _iterators.length
? _iterators[_currentIterator].moveNext()
: false;
}
}
3. 无限序列迭代器
class FibonacciIterator implements Iterator<int> {
int _a = 0, _b = 1;
int get current => _a;
bool moveNext() {
final next = _a + _b;
_a = _b;
_b = next;
return true; // 无限序列总是返回true
}
}
// 使用
final fib = FibonacciIterator();
for (var i = 0; i < 10; i++) {
fib.moveNext();
print(fib.current); // 0, 1, 1, 2, 3, 5...
}
总结:迭代器模式是你的集合导航仪
- 核心价值: 提供统一的遍历接口,解耦集合结构与遍历逻辑
- Flutter优势:
- 简化复杂数据结构的遍历
- 实现懒加载和分页机制
- 支持多种遍历顺序和过滤条件
- 与Dart的Iterable完美结合
- 适用场景: 社交动态流、树形菜单、分页列表、图形绘制
🔄 设计启示: 当你需要以不同方式"浏览"数据集时,迭代器模式就是你的"导航按钮",让数据流动尽在掌控!
更多推荐

所有评论(0)