迭代器模式 - Flutter中的集合导航专家,解锁数据遍历的无限可能!

自定义滚动效果/树形结构遍历/分页加载…用迭代器掌控数据流动的节奏


痛点场景:多源数据混合遍历

假设你的社交应用需要显示以下内容:

  1. 本地缓存的帖子
  2. 新收到的实时消息
  3. 推荐广告
  4. 朋友动态

这些数据来自不同接口,结构各异:

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;
}

问题爆发点:

  • 遍历逻辑分散在各处
  • ⏳ 需要手动处理异步数据
  • 插入顺序难以维护
  • 新增数据源需要修改核心代码

迭代器模式解决方案

核心思想: 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部表示。

三个关键角色:

  1. 迭代器接口(Iterator): 定义遍历操作
  2. 具体迭代器(ConcreteIterator): 实现遍历逻辑
  3. 可迭代集合(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]);
      },
    );
  }
)

迭代器模式最佳实践

  1. 何时使用迭代器模式:

    • 需要统一遍历不同类型的集合
    • 需要支持多种遍历方式(正序、逆序、过滤等)
    • 不希望暴露集合内部结构
    • 需要延迟加载或分页处理大数据集
  2. 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; // 逐个产出,避免一次性加载
        }
      }
    }
    
  3. 性能优化技巧:

    // 懒加载迭代器
    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;
      }
    }
    
  4. 测试策略:

    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完美结合
  • 适用场景: 社交动态流、树形菜单、分页列表、图形绘制

设计启示: 当你需要以不同方式"浏览"数据集时,迭代器模式就是你的"导航按钮",让数据流动尽在掌控!

你可能感兴趣的:(flutter,迭代器模式,flutter)