首页 文章

在Flutter中使用Stream / Sink

提问于
浏览
1

我正在尝试使用来自Dart API的Streams替换 increment 颤振的应用代码,而不使用scoped_modelrxdart .

所以我读了this并看了this,但无法让它对我有用,我的代码是:

StreamProvider.dart

import 'package:flutter/widgets.dart';
import 'businessLogic.dart';
import 'dart:async';

class Something {

  final _additionalContrllerr = StreamController<int>();
  Sink<int> get addition => _additionalContrllerr.sink;

  Stream<int> get itemCount =>  _additionalContrllerr.stream;
}

class StreemProvider extends InheritedWidget {
  final Something myBloc;  // Business Logic Component

  StreemProvider({
    Key key,
    @required this.myBloc,
    Widget child,
  }) : super(key: key, child: child);

  @override
  bool updateShouldNotify(InheritedWidget oldWidget) => true;

  static Something of(BuildContext context) =>
      (context.inheritFromWidgetOfExactType(StreemProvider) as StreemProvider)
          .myBloc;
}

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_app/StreemProvider.dart';

void main() => runApp(MyApp(
  textInput: Text("Provided By the Main"),
));

class MyApp extends StatefulWidget {
  final Widget textInput;
  MyApp({this.textInput});

  @override
  State<StatefulWidget> createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  bool checkBoxValue = false;

  int _counter = 0;
  @override
  Widget build(BuildContext ctxt) {
    var x = Something();      //// Not sure if have to use this!
    return StreemProvider(
      myBloc: x,              //// Not sure about this!!
      child: MaterialApp(
      home: SafeArea(
           child: Scaffold(
              body: new Center(
              child: new Column(
              children: <Widget>[
                widget.textInput,
                Text("clickec $_counter times"),
                Text("clickec ${x.itemCount.listen((int i) => i)} times"),
      /// How to get the value of i??!
                Checkbox(
                    value: checkBoxValue,
                    onChanged: (bool newValue){
                      setState(() {
                        checkBoxValue = newValue;
                      });
                    }
                )
              ],
            )),
             floatingActionButton: Incrementer(_increment),
            // floatingActionButton: Incrementer(x),
           ),
          ),
      ),
    );
  }

  _increment() {
    setState(() {
      _counter += 1;
    });
  }
}

class Incrementer extends StatefulWidget {

  final Function increment;

  Incrementer(this.increment);

  @override
  State<StatefulWidget> createState() {
    return IncrementerState();
  }
}
  class IncrementerState extends State<Incrementer>{
    @override
    Widget build(BuildContext ctxt) {
      final myBloc = StreemProvider.of(context);
      return new FloatingActionButton(
        //onPressed: widget.increment,
        // How ot get the latest value!!
        onPressed: () async {
          var y =  await myBloc.itemCount.last;
          if (y.isNaN) y = 0;
          myBloc.addition.add(y+1);
        },
        child: new Icon(Icons.add),
        );
    }
  }

2 回答

  • -1

    不知道对rx_dart的限制,但我只能尝试使用它来回答 . 大声笑

    你的团队没有定义要在你的输入流中监听的东西,这就是我可以让它工作的方式

    counter_bloc.dart

    import 'package:rxdart/rxdart.dart';
    import 'dart:async';
    
    class CounterBloc {
      int _count = 0;
    
      ReplaySubject<int> _increment = ReplaySubject<int>();
      Sink<int> get increment => _increment;
    
      BehaviorSubject<int> _countStream = BehaviorSubject<int>(seedValue: 0);
      Stream<int> get count => _countStream.stream;
    
      CounterBloc() {
        _increment.listen((increment) {
          _count += increment;
          _countStream.add(_count);
        });
      }
    }
    

    在构造函数中,为该流设置listen方法 . 对于每个发送的增量,它将递增计数器并将当前计数发送到另一个流 .

    main.dart 中,删除了_counter属性,因为它现在由BLOC处理 . 并显示我使用了流构建器 .

    还增加了第二个晶圆厂,用2个增量来测试逻辑 .

    希望这可以帮助你模拟你的集团类 . :)

    一个好的集团参考:https://www.youtube.com/watch?v=PLHln7wHgPE

    main.dart

    import 'counter_bloc.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      CounterBloc bloc = CounterBloc();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
                StreamBuilder<int>(
                  stream: bloc.count,
                  initialData: 0,
                  builder: (BuildContext c, AsyncSnapshot<int> data) {
                    return Text(
                      '${data.data}',
                      style: Theme.of(context).textTheme.display1,
                    );
                  },
                ),
              ],
            ),
          ),
          floatingActionButton: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              FloatingActionButton(
                onPressed: () {
                  bloc.increment.add(2);
                },
                tooltip: 'Increment 2',
                child: Text("+2"),
              ),
              FloatingActionButton(
                onPressed: () {
                  bloc.increment.add(1);
                },
                tooltip: 'Increment 1',
                child: Text("+1"),
              ),
            ],
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    
  • -1

    非常感谢vbandrade他的回答帮助我搞清楚了 . 与我合作的解决方案是:

    如果我需要在 bloc 业务逻辑组件中监听 sink ,然后处理并输出到其他元素,我需要2 StreamController .

    counter_bloc.dart 是:

    import 'dart:async';
    
    class CounterBloc {
      int _count = 0;
    
      // The controller to stream the final output to the required StreamBuilder
      final _counter = StreamController.broadcast<int>();
      Stream<int> get counter => _counter.stream;
    
      // The controller to receive the input form the app elements     
      final _query = StreamController<int>();
      Sink<int> get query => _query.sink;
      Stream<int> get result => _query.stream;
    
      // The business logic
      CounterBloc() {
        result.listen((increment) {     // Listen for incoming input         
          _count += increment;          // Process the required data
          _counter.add(_count);         // Stream the required output
        });
      }
    
      void dispose(){
        _query.close();
        _counter.close();
      }
    }
    

    main.dart 是:

    import 'counter_bloc.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      State<StatefulWidget> createState() {
        return _MyHomePageState();
      }
    
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      var bloc = CounterBloc();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
                StreamBuilder<int>(      // Listen to the final output sent from the Bloc
                  stream: bloc.counter,
                  initialData: 0,
                  builder: (BuildContext c, AsyncSnapshot<int> data) {
                    return Text(
                      '${data.data}',
                      style: Theme.of(context).textTheme.display1,
                    );
                  },
                ),
              ],
            ),
          ),
          floatingActionButton: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              FloatingActionButton(
                onPressed: () {
                  bloc.query.add(2);         // Send input to the Bloc
                },
                tooltip: 'Increment 2',
                child: Text("+2"),
              ),
              FloatingActionButton(
                onPressed: () {
                  bloc.query.add(1);        // Send input to the Bloc
                },
                tooltip: 'Increment 1',
                child: Text("+1"),
              ),
            ],
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    

相关问题