Flutter流式数据构建插件sliver_stream_builder的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter流式数据构建插件sliver_stream_builder的使用

sliver_stream_builder 是一个用于将数据流(stream)转换为 SliverListSliverGrid 的插件。它还提供了一个辅助函数来从下一个函数创建流。

使用

简单用法示例

CustomScrollView(
  slivers: [
    SliverStreamBuilder<NewsModel>(
      stream: NewsNetwork.getNews(), // 数据流
      builder: (ctx, item) => NewsItem(news: item), // 构建器
    )
  ],
);

在这个例子中,我们使用 SliverStreamBuilder 将来自 NewsNetwork.getNews() 的数据流转换为 SliverList,并使用 NewsItem 构建每个新闻项。

自定义 Sliver 构建器

CustomScrollView(
  slivers: [
    SliverStreamBuilder<String>(
      stream: ImageNetwork.getImages(), // 图片数据流
      sliverBuilder: (context, delegate) => SliverGrid(
        delegate: delegate, // 委托
        gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
          maxCrossAxisExtent: 150, // 每个项目的最大交叉轴尺寸
        ),
      ),
      itemBuilder: (ctx, url) => CachedNetworkImage(imageUrl: url), // 构建每个图片项
    ),
  ],
);

在这个例子中,我们将图片数据流转换为 SliverGrid,每个项目使用 CachedNetworkImage 显示图片。

包含空构建器

CustomScrollView(
  slivers: [
    SliverStreamBuilder<NewsModel>(
      stream: NewsNetwork.getNews(), // 数据流
      builder: (ctx, item) => NewsItem(news: item), // 构建器
      // 当流完成且未发出任何元素时显示
      emptyBuilder: (_) => Center(child: Text('Nothing new here :(')), 
    )
  ],
);

在这个例子中,如果流完成且没有发出任何元素,将会显示一个提示用户“没有新消息”的中心文本。

从下一个函数创建流

dataStreamWrapper 方法

// 手动管理状态
Stream<NewsModel> getNews() {
  int page = 0;
  return dataStreamWrapper(() async {
    final ans = await dio.get('/news', queryParameters: {'page': page});
    final data = (ans.data as List).map((e) => NewsModel.fromJson(e)).toList();
    if (data.isEmpty) return null;
    // 只在这里增加页码以允许重新获取相同的数据,如果抛出异常
    // 此函数内部的所有错误都会被捕获并添加到流中
    page += 1;
    return data;
  });
}

dataStreamWrapper 函数负责管理流控制器,并将下一个函数转换为流。它实现了暂停、恢复逻辑以及错误处理。

dataStreamHelper 方法

// 更安全的方法来创建数据流,因为它防止了一些误用
Stream<NewsModel> getNews() {
  return dataStreamHelper.state(0).next((it) async {
    final ans = await dio.get('/news', queryParameters: {'page': it.current});
    final data = (ans.data as List).map((e) => NewsModel.fromJson(e)).toList();
    if (data.isEmpty) return it.done(); // 如果数据为空,则表示完成
    return it.next(
      data, 
      it.current + 1, // 下一个状态
    );
  });
}

dataStreamHelper 是一个更安全的方法来创建数据流,因为它可以防止一些误用。

示例代码

以下是从 GitHub 获取的示例代码:

import 'package:examples/data_stream.dart';
import 'package:examples/empty.dart';
import 'package:examples/images_grid.dart';
import 'package:examples/simple.dart';
import 'package:flutter/material.dart';

import 'error.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Builder(builder: (context) {
        return Scaffold(
          appBar: AppBar(title: const Text('SliverStreamBuilder example')),
          body: ListView(
            children: [
              ListTile(
                title: const Text('Grid sliver'),
                onTap: () => Navigator.push(
                  context,
                  MaterialPageRoute(builder: (_) => const ImagesGrid()),
                ),
              ),
              ListTile(
                title: const Text('Empty'),
                onTap: () => Navigator.push(
                  context,
                  MaterialPageRoute(builder: (_) => const EmptyStream()),
                ),
              ),
              ListTile(
                title: const Text('Simple list'),
                onTap: () => Navigator.push(
                  context,
                  MaterialPageRoute(builder: (_) => const SimpleSliver()),
                ),
              ),
              ListTile(
                title: const Text('Data Stream example'),
                onTap: () => Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (_) => const DataStreamExample(),
                  ),
                ),
              ),
              ListTile(
                title: const Text('Data Stream error example'),
                onTap: () => Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (_) => const SliverStreamErrorExample(),
                  ),
                ),
              ),
            ],
          ),
        );
      }),
    );
  }
}

更多关于Flutter流式数据构建插件sliver_stream_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter流式数据构建插件sliver_stream_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter中使用sliver_stream_builder插件来处理流式数据的示例代码。这个插件非常适合于处理大量动态数据,例如从Firestore或WebSocket接收的实时数据。

首先,确保你已经在pubspec.yaml文件中添加了sliver_stream_builder依赖:

dependencies:
  flutter:
    sdk: flutter
  sliver_stream_builder: ^x.y.z  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖。

以下是一个完整的示例代码,展示如何使用SliverStreamBuilder来构建流式数据列表:

import 'package:flutter/material.dart';
import 'package:sliver_stream_builder/sliver_stream_builder.dart';
import 'dart:async';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SliverStreamBuilder Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 创建一个StreamController来模拟流式数据
  final StreamController<List<String>> _controller = StreamController<List<String>>();

  @override
  void initState() {
    super.initState();
    // 模拟每隔2秒添加一个新数据项
    Timer.periodic(Duration(seconds: 2), (timer) {
      final newItem = 'Item ${_controller.value.last?.length ?? 0 + 1}';
      _controller.add([..._controller.value, newItem]);
    });

    // 初始化时添加一个初始数据项
    _controller.add(['Initial Item']);
  }

  @override
  void dispose() {
    _controller.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SliverStreamBuilder Demo'),
      ),
      body: CustomScrollView(
        slivers: <Widget>[
          SliverStreamBuilder<List<String>>(
            stream: _controller.stream,
            initialData: [], // 初始数据(可选)
            builder: (context, snapshot) {
              // 处理快照数据并返回SliverList
              return SliverList(
                delegate: SliverChildBuilderDelegate(
                  (context, index) {
                    return ListTile(
                      title: Text(snapshot.data[index]),
                    );
                  },
                  childCount: snapshot.data.length,
                ),
              );
            },
          ),
        ],
      ),
    );
  }
}

代码解释:

  1. 依赖管理:确保在pubspec.yaml中添加了sliver_stream_builder依赖。

  2. 数据模拟

    • 使用StreamController<List<String>>来模拟流式数据。
    • initState中,使用Timer.periodic每隔2秒向流中添加一个新数据项。
    • 初始化时,添加一个初始数据项。
  3. UI构建

    • 使用CustomScrollViewSliverStreamBuilder来构建UI。
    • SliverStreamBuilderstream属性绑定到StreamController的流。
    • builder回调中,使用SliverListSliverChildBuilderDelegate来构建列表项。
  4. 资源清理

    • dispose方法中关闭StreamController,以防止内存泄漏。

这个示例展示了如何使用SliverStreamBuilder来动态地构建和更新一个流式数据列表。你可以根据需要调整数据获取逻辑和UI布局。

回到顶部