【问题标题】:Using Stream/Sink in Flutter在 Flutter 中使用 Stream/Sink
【发布时间】:2018-06-22 20:34:23
【问题描述】:

我正在尝试通过使用 Dart API 中的 Streams 而不使用 scoped_modelrxdart 来替换 increment 颤振应用程序代码。

所以我阅读了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),
        );
    }
  }

【问题讨论】:

    标签: dart flutter


    【解决方案1】:

    一个简单的实现

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Counter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      int _counter = 0;
    
      final StreamController<int> _streamController =
          StreamController<int>.broadcast();
    
      Stream<int> get _stream => _streamController.stream;
    
      void incrementCounter() {
        _counter++;
        _streamController.add(_counter);
        
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Flutter demo'),
          ),
          body: Center(
            child: StreamBuilder<int>(
                stream: _stream,
                builder: (ctxt, snapshot) {
                  if (snapshot.hasData) {
                    return Text(
                        'You have pushed this button ${snapshot.data} times');
                  }
                  return Text('You have pushed this button ${0} times');
                }),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              incrementCounter();
            },
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案2】:

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

      如果我需要在我的bloc 业务逻辑组件中收听sink,我需要有2 个StreamController,然后处理并将stream 输出到其他元素。

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

      【讨论】:

      • 我喜欢这让集团有机会处理从视图输入的数据。这也支持了 bloc 实例应该只公开接收器和流的概念
      • 我看过很多 bloc 示例,但我想知道在将数据添加到流后我们如何获得一些返回值,如何从语句 'bloc.query.add(2) 获得返回值给 UI
      【解决方案3】:

      不知道 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);
          });
        }
      }
      

      在构造函数中,为该流设置了监听方法。对于发送的每个增量,它都会增加计数器并将当前计数发送到另一个流。

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

      还添加了第二个晶圆厂,增量为 +2 以测试逻辑。

      希望这可以帮助您为 bloc 类建模。 :)

      一个好的集团参考: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.
          );
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-10-25
        • 1970-01-01
        • 1970-01-01
        • 2021-10-03
        • 1970-01-01
        • 2020-02-25
        • 1970-01-01
        • 1970-01-01
        • 2020-03-12
        相关资源
        最近更新 更多