Flutter教程- Async(四) Stream和StreramBuilder组件案例详解


发文时间:2022年04月14日 18:16:35     编辑:Aaron      标签:Flutter异步(Async) 图文详解系列 727


本文将介绍Stream的使用,包括如何用listen方法或用StreamBuilder组件监听、和广播等。

 让stream源源不断的输出信息~

//让stream不停的输出值 
final stream =Stream.periodic(Duration(seconds: 1),(_){
 return 42;
});

@override
void initState() {
  stream.listen((event) {
    print(event);
  });
  // TODO: implement initState
  super.initState();
}

flutter: 42
flutter: 42
flutter: 42
flutter: 42
flutter: 42
flutter: 42
flutter: 42
....n

image.png

import 'dart:async';

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Aaron FutureBuilder Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Aaron FutureBuilder Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  int _counter = 0;
  void _incrementCounter() async {
    setState(() {
      this._counter++;
    });
  }

  //让stream不停的输出值
  // final stream = Stream.periodic(Duration(seconds: 2), (_) => 42);

  //定义当前广播
  StreamController controller;
  void openStream() {
    print('开启stream流');

    /*
     非广播模式 - 只支持单个监听stream 且会做数据缓存。
      假设你当前延时3秒才显示stream流的数据,在非广播模式下数据会缓存下来,
      3秒后输出延时期间的值。
     */
    // controller=StreamController.broadcast();

    //广播模式 - 广播模式下支持多个监听stream 但是不会做数据缓存
    controller = StreamController.broadcast();
  }

  @override
  void initState() {

    //验证stream广播
    Future.delayed(Duration(seconds: 1), () {
      controller.stream.listen((event) {
        print('当前数据: ${event}');
      },
          onError: (err) => print('当前发生错误 ${err}'),
          onDone: () => print('全部获取完毕,已关闭'));
    });

    //开启stream
    this.openStream();
    super.initState();
  }

  @override
  void dispose() {
    //页面销毁时关闭stream
    controller.close();
    super.dispose();
  }


  //TODO  1、async await和stream的语法糖
  Future  getId() async{
    return   123;
  }

  //TODO  2 实时返回当前时间

  /*
  知识扩展:flutter函数中使用async,async*使得函数异步执行,
  两者的差别在于。async*返回Stream,并通过yield关键字生成Stream流的值,
   */
  Stream getTime()async*{
    while(true){
      await Future.delayed(Duration(seconds: 1));
      yield  DateTime.now();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: DefaultTextStyle(
           //该组件下设置下字体跟APP的字体一致
          style: Theme.of(context).textTheme.headline4, 
          child: Column(
            children: [
              // ignore: deprecated_member_use
              RaisedButton(
                  child: Text('往流加10'),
                  onPressed: () {
                    controller.sink.add(10);
                  }),
              // ignore: deprecated_member_use
              RaisedButton(
                  child: Text('往流加66'),
                  onPressed: () {
                    controller.sink.add(66);
                  }),
              // ignore: deprecated_member_use
              RaisedButton(
                  child: Text('往流加 hi'),
                  onPressed: () {
                    controller.sink.add('hi');
                  }),
              // ignore: deprecated_member_use
              RaisedButton(
                  child: Text('Error'),
                  onPressed: () {
                    controller.sink.addError('Error 错误');
                  }),
              // ignore: deprecated_member_use
              RaisedButton(
                  child: Text('关闭流'),
                  onPressed: () {
                    controller.sink.close();
                  }),

              // ignore: deprecated_member_use
              RaisedButton(
                  child: Text('开启流'),
                  onPressed: () {
                    this.openStream();
                    //重置下build
                    setState(() {});
                  }),

              StreamBuilder(
 //可以在stream做一些map的操作  - 
 // distinct意思为若当前stream的值和前一次的一样,那么build不会被重置
 stream: controller.stream.where((event) => event>5).map((event) 
 => event*2).distinct(),
                builder:
                    (BuildContext context, AsyncSnapshot                     snapshot) {
   print('------------------当前build已重置------------------');
                  switch (snapshot.connectionState) {
                    case ConnectionState.none:
                      return Text('当前stream为空');
                      break;
                    case ConnectionState.waiting:
                      return Text('等待数据中....');
                      break;
                    case ConnectionState.active:
                      if (snapshot.hasError) {
                        return Text('获取数据出错咯 ${snapshot.error}');
                      }
                      return Text("当前数据:${snapshot.data}");
                      break;
                    case ConnectionState.done:
                      return Text("数据已经全部获取完毕!已关闭!");
                      break;
                  }
                  return Text('空');
                },
              ),

              StreamBuilder(
                stream: getTime(),
                builder: (BuildContext context, AsyncSnapshot                 snapshot) {
                  switch (snapshot.connectionState) {
                    case ConnectionState.none:
                      return Text('当前stream为空');
                      break;
                    case ConnectionState.waiting:
                      return Text('等待数据中....');
                      break;
                    case ConnectionState.active:
                      if (snapshot.hasError) {
                        return Text('获取数据出错咯 ${snapshot.error}');
                      }
                      return Text("当前数据:${snapshot.data}");
                      break;
                    case ConnectionState.done:
                      return Text("数据已经全部获取完毕!已关闭!");
                      break;
                  }
                    return Text('空');
                },

              ),

            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer 
      //for build methods.
    );
  }
}

class TestBox extends StatefulWidget {
  final Color color;
  TestBox(this.color, {Key key}) : super(key: key);

  @override
  _TestBoxState createState() => _TestBoxState();
}

class _TestBoxState extends State {
  int count = 0;
  @override
  Widget build(BuildContext context) {
    return Container(
        width: 150,
        height: 150,
        color: widget.color,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('$count', style: TextStyle(color: Colors.white)),
            IconButton(
              onPressed: () {
                setState(() {
                  print('当前值发生改变 ${count}');
                  count++;
                });
              },
              icon: Icon(Icons.add),
            )
          ],
        ));
  }
}



                                                 甘心情愿

 

若无特殊说明,此文章为博主原创。
写稿不易,如需转载,请注明出处: https://www.aaroner.cn/art/54.html




SITE MAP

  FOLLOW US