首页 > 其他分享 >Stream (是异步版本的列表)、StreamBuilder(局部数据更新)

Stream (是异步版本的列表)、StreamBuilder(局部数据更新)

时间:2024-01-17 22:11:47浏览次数:27  
标签:StreamBuilder 异步 const Stream Text controller child return

Stream 流

Stream的字面意思是水流,Stream不像Future那样只会在未来获取一个值,它可以异步获取0个或者 多个值。如果说Future是一个异步版本的int或者String,Stream则更像是异步版本的列表,List,List, 列表里面可能会有0个或者多个元素。
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  
  Future<String> loadData() async {
    return "这是一个Flutter"; // 正常返回数据
  }

//定义一个异步流
  Stream<int> loadDataStream() {
    return Stream.periodic(Duration(seconds: 1), (v) => v);
  }

  @override
  void initState() {
    super.initState();
    // 获取异步方法的数据
    loadData().then((value) => print(value)); //打印数据
//获取异步流的数据
    loadDataStream().listen((event) {
      print("stream--------------------------:$event");
    });
  }

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text("Text"),
    );
  }
}

StreamBuilder  局部数据更新

在 Flutter 中,StreamBuilder 是一个将 Stream 流与 Widget结合到一起的组件,可实现组件的局部数 据更新 , StreamBuilder 组件和FutureBuilder组件比较相似,不同点在于它是一个可以自动跟踪Stream (数据流或事件流)的状态,并在Stream有变化时自动重绘的组件。Stream不同于Future,可能会在 生命周期内释放出任意数量的数据值(正常)或者错误信息(异常),通常被用于读取文件或者下载网 络资源等操作,也有时候用于状态管理。 StreamBuilder主要功能:
  1. 实现局部刷新
  2. 读取流实现读取文件或者下载网络资源等操作
  3. 父子组件之间的数据广播
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
//定义一个异步流
  Stream<int> loadDataStream() {
    return Stream.periodic(Duration(seconds: 1), (v) {
      if (Random().nextBool()) {
        //随机生成一个true或者false
        return v;
      }
      throw "这是一个异常";
    });
  }

  @override
  void initState() {
    super.initState();

//获取异步流的数据
    loadDataStream().listen((event) {
      print("stream--------------------------:$event");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: StreamBuilder(
          stream: loadDataStream(), //获取流
          builder: (context, snapshot) {
            // 观察ConnectionState的状态
            print(snapshot.connectionState); //获取状态
            switch (snapshot.connectionState) {
              case ConnectionState.none:
                return const Center(
                  child: Text("NONE: 没有数据流"),
                );
              case ConnectionState.waiting: //等待中
                return const Center(child: Text("WAITING: 等待数据流"));
              case ConnectionState.active: //正常运行状态
                if (snapshot.hasError) {
                  //隐藏
                  return Center(
                      child: Text("ACTIVE: 数据流活跃,异常: ${snapshot.error}"));
                } else {
                  return Center(
                      child: Text("ACTIVE: 数据流活跃,数据: ${snapshot.data}"));
                }
              case ConnectionState.done: //结束
                return const Center(child: Text("DONE: 数据流关闭"));
              default:
                throw "ConnectionState没有别的状态"; //抛异常
            }
          }),
    );
  }
}

StreamController  异步数据流的监听、添加数据、关闭流等操作

创建更精确的数据流
class DemoPage extends StatefulWidget {
  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
// 定义一个类型为int的Stream
  final _controller = StreamController<int>();
  @override
  void dispose() {
    super.dispose();
    _controller.close();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Stream Demo"),
      ),
      body: Wrap(
        spacing: 20,
        children: [
          ElevatedButton(
// 按钮点击后Stream会释放出数字1
            child: const Text("Emit 1"),
            onPressed: () => _controller.add(1),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出数字2
            child: const Text("Emit 2"),
            onPressed: () => _controller.add(2),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出一个错误
            child: const Text("Emit Error"),
            onPressed: () => _controller.addError("500 错误"),
          ),
          ElevatedButton(
// 按钮点击后Stream会关闭
            child: const Text("Close"),
            onPressed: () => _controller.close(), //关闭流 一般不手动关闭
          ),
          StreamBuilder(
            stream: _controller.stream,
            builder: (context, snapshot) {
              print("正在重新绘制StreamBuilder组件…");
              if (snapshot.connectionState == ConnectionState.done) {
                //判断流是否关闭
                return const Text("数据流已关闭");
              }
              if (snapshot.hasError) return Text("${snapshot.error}"); //流中有异常
              if (snapshot.hasData) return Text("${snapshot.data}");
              return const Center(
                child: CircularProgressIndicator(), //圈圈
              );
            },
          )
        ],
      ),
    );
  }
}

StreamController.broadcast() 多个监听者

StreamController 默认只能有一个监听这,如果有多个监听者的话就需要用 StreamController.broadcast()
class DemoPage extends StatefulWidget {
  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  //broadcast创建的流可以有多个监听者
  final _controller = StreamController.broadcast();
  @override
  void initState() {
// TODO: implement initState
    super.initState();
    _controller.stream.listen((event) {  //监听
      print("-----------------------------------$event");
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Stream Demo"),
      ),
      body: Wrap(
        spacing: 20,
        children: [
          ElevatedButton(
// 按钮点击后Stream会释放出数字1
            child: const Text("Emit 1"),
            onPressed: () => _controller.add(1),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出数字2
            child: const Text("Emit 2"),
            onPressed: () => _controller.add(2),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出一个错误
            child: const Text("Emit Error"),
            onPressed: () => _controller.addError("oops"),
          ),
          ElevatedButton(
// 按钮点击后Stream会关闭
            child: const Text("Close"),
            onPressed: () => _controller.close(),
          ),
          StreamBuilder(
            stream: _controller.stream, // 去除重复的数据
            builder: (context, snapshot) {
              print("正在重新绘制StreamBuilder组件…");
              if (snapshot.connectionState == ConnectionState.done) {
                return const Text("数据流已关闭");
              }
              if (snapshot.hasError) return Text("${snapshot.error}");
              if (snapshot.hasData) return Text("${snapshot.data}");
              return const Center(
                child: CircularProgressIndicator(),
              );
            },
          )
        ],
      ),
    );
  }
}

Stream过滤

class DemoPage extends StatefulWidget {
  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
// 定义一个类型为int的Stream
  final _controller = StreamController.broadcast();
  @override
  void initState() {
// TODO: implement initState
    super.initState();
    _controller.stream.listen((event) {
      print(event);
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Stream Demo"),
      ),
      body: Wrap(
        spacing: 20,
        children: [
          ElevatedButton(
// 按钮点击后Stream会释放出数字1
            child: const Text("Emit 1"),
            onPressed: () => _controller.add(1),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出数字2
            child: const Text("Emit 2"),
            onPressed: () => _controller.add(2),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出数字1
            child: const Text("Emit 3"),
            onPressed: () => _controller.add(3),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出数字1
            child: const Text("Emit 4"),
            onPressed: () => _controller.add(4),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出数字1
            child: const Text("Emit 5"),
            onPressed: () => _controller.add(5),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出数字1
            child: const Text("Emit 6"),
            onPressed: () => _controller.add(6),
          ),
          ElevatedButton(
// 按钮点击后Stream会释放出一个错误
            child: const Text("Emit Error"),
            onPressed: () => _controller.addError("oops"),
          ),
          ElevatedButton(
// 按钮点击后Stream会关闭
            child: const Text("Close"),
            onPressed: () => _controller.close(),
          ),
          StreamBuilder(
            stream: _controller.stream
                .where((event) => event > 3) //过滤大于3
                .map((event) => event * 2)  //配置流 * 2
                .distinct(), // 去除重复的数据
            builder: (context, snapshot) {
              print("正在重新绘制StreamBuilder组件…");
              if (snapshot.connectionState == ConnectionState.done) {
                return const Text("数据流已关闭");
              }
              if (snapshot.hasError) return Text("${snapshot.error}");
              if (snapshot.hasData) return Text("${snapshot.data}");
              return const Center(
                child: CircularProgressIndicator(),
              );
            },
          )
        ],
      ),
    );
  }
}

 

 

 

标签:StreamBuilder,异步,const,Stream,Text,controller,child,return
From: https://www.cnblogs.com/xbinbin/p/17971141

相关文章

  • Fetch方法——一种简单合理的跨网络异步获取资源方式
    FetchAPI是一个JavaScript接口,用于访问和操纵HTTP管道的一些具体部分,例如请求和响应。FetchAPI提供了一个全局fetch()方法,一种简单,合理的来跨网络异步获取资源的方式。一个基本的fetch请求:fetch("http://localhost:4000/datas.json",{method:"POST",......
  • Java异步编程详解
    在现代应用程序开发中,异步编程变得越来越重要,特别是在处理I/O密集型任务时。Java提供了一套强大的异步编程工具,使得开发者能够更有效地处理并发任务。本篇博文将深入探讨Java中异步编程的方方面面,通过具体例子详细说明异步编程的实践。异步编程的背景在传统的同步编程模型中,任务......
  • 多个异步请求的执行顺序
    Fn(){ //以下两个都为异步请求 this.getData1() this.getData2()}this.Fn()我以为的执行顺序是:getData1-->getData2但其实,顺序不一定,getData1有时在前,有时在后。解决:加上async和awaitasyncFn(){ //以下两个都为异步请求 awaitthis.getData1() awaitthi......
  • Future异步
    在其他语言,比如java、c++中,同时要执行多个任务可以使用多线程来实现。而在Dart语言中没有线程和进程的概念,它是单线程+事件循环的设计模式,Dart和Flutter中要同时执行多个任务可以使用异步来实现,Flutter中主要使用Future来实现异步操作。 Future返回值 Future是一个泛......
  • Gstreamer Rtspsrc连接大华摄像头失败原因及解决
    先说解决办法sudoapt-getremovegstreamer1.0-plugins-ugly分析过程和原因输入命令gst-launch-1.0rtspsrclocation="rtsp/url"!fakesink终端输出如下SettingpipelinetoPAUSED...PipelineisliveanddoesnotneedPREROLL...Progress:(open)OpeningStre......
  • Flink异步IO
    本文讲解Flink用于访问外部数据存储的异步I/OAPI。对于不熟悉异步或者事件驱动编程的用户,建议先储备一些关于Future和事件驱动编程的知识。对于异步I/O操作的需求在与外部系统交互(用数据库中的数据扩充流数据)的时候,需要考虑与外部系统的通信延迟对整个流处理应用的影响......
  • Python 异步编程原理篇之新旧协程实现对比
    协程的发展流程再来回顾一下协程的发展流程:python2.5为生成器引用.send()、.throw()、.close()方法python3.3为引入yieldfrom,可以接收返回值,可以使用yieldfrom定义协程Python3.4加入了asyncio模块Python3.5增加async、await关键字,在语法层面的提供支持python3.7使用......
  • SparkStreaming 连接 Kafka数据源
    本文的前提条件:SparkStreaminginJava参考地址:SparkStreaming+KafkaIntegrationGuide(Kafkabrokerversion0.10.0orhigher)1.添加POM依赖<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>......
  • Stream API
    StreamAPI概念:StreamAPI是Java8中处理集合的关键抽象概念,StreamAPI允许开发人员在不改变原始数据源的情况下对集合进行操作(查找、过滤、数据映射等等),这使得代码更加简洁、易读和可维护。总之,StreamAPI提供了一种高效且易于使用的数据处理方式注意点:Stream不会存储数据......
  • SparkStreaming 自定义数据采集器
    本文的前提条件:SparkStreaminginJava参考地址:SparkStreamingCustomReceivers1.自定义数据采集器packagecn.coreqi.receiver;importorg.apache.spark.storage.StorageLevel;importorg.apache.spark.streaming.receiver.Receiver;importjava.util.Random;/**......