在一个简单的 BLoC 示例中使用 Streams/Sinks

Use of Streams/Sinks in a simple BLoC Example

我正在尝试理解一个应用程序的简单 BLoC 示例,该应用程序 increments/decrements 一个基于按钮的计数器(即默认的 Flutter 应用程序,添加了一个用于递减计数器的按钮)。

我无法理解为什么我们需要在 class 中管理三个 streams/sinks CounterBloc:

  1. StreamSink<int> get _inCounter => _counterStateController.sink;
  2. Stream<int> get counter => _counterStateController.stream;
  3. Sink<CounterEvent> get counterEventSink => _counterEventController.sink;

特别是,为什么我们需要 _inCountercounter 的单独变量?

完整代码如下:

counter_event.dart:


class IncrementEvent extends CounterEvent {}

class DecrementEvent extends CounterEvent {}

counter_bloc.dart:

import 'package:flutter_bloc/counter_event.dart';

class CounterBloc {
  int _counter = 0;

  final _counterStateController = StreamController<int>();
  StreamSink<int> get _inCounter => _counterStateController.sink;
  Stream<int> get counter => _counterStateController.stream;

  final _counterEventController = StreamController<CounterEvent>();
  Sink<CounterEvent> get counterEventSink => _counterEventController.sink;

  CounterBloc() {
    _counterEventController.stream.listen(_mapEventToState);
  }

  _mapEventToState(CounterEvent event) {
    if (event is IncrementEvent)
      _counter++;
    else
      _counter--;

    _inCounter.add(_counter);
  }

  void dispose() {
    _counterStateController.close();
    _counterEventController.close();
  }
}

main.dart的相关摘录:

class _MyHomePageState extends State<MyHomePage> {
  final _bloc = CounterBloc();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: StreamBuilder(
          stream: _bloc.counter,
          initialData: 0,
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '${snapshot.data}',
                  style: Theme.of(context).textTheme.headline4,
                ),
              ],
            );
          },
        ),
      ),```

首先你需要明白我们使用的是StreamController,它基本上就像一个管道。您使用 sink 放置一个值,然后使用 stream.

在另一端获得该值

我们将 _counterStateController 声明为 StreamController 以控制 _counter 值。无论您通过 _inCounter 传递什么值,您都将使用流 counter

获得该值
  final _counterStateController = StreamController<int>();
  StreamSink<int> get _inCounter => _counterStateController.sink;
  Stream<int> get counter => _counterStateController.stream; 

另一个接收器 counterEventSink_counterEventController StreamController 的接收器,您可以将其用于控制​​器 CounterEvent、IncrementEvent 或 DecrementEvent。

  final _counterEventController = StreamController<CounterEvent>();
  Sink<CounterEvent> get counterEventSink => _counterEventController.sink;

无论您在接收器 _counterEventController 中放置什么值 counterEventSink,您都将通过它的流获得该值,我们将在创建 CounterBloc 时收听该流对象。

 CounterBloc() {
    _counterEventController.stream.listen(_mapEventToState); //listening to the CounterEvent Stream
  }

这里我们将 _mapEventToState 函数作为回调传递。每当您向 counterEventSink.

中输入任何值时,都会调用此函数

_mapEventToState 中,我们只是检查传递的事件类型,然后将该值添加到 _inCounter,即 _counterStateController 的流。因此,您添加到 _inCounter 的任何内容都将通过 counter.

接收
_mapEventToState(CounterEvent event) {
    if (event is IncrementEvent)
      _counter++;
    else
      _counter--;

    _inCounter.add(_counter);
  }