将BLoC接收器与另一个BLoC连接

时间:2018-11-11 23:42:18

标签: dart flutter

我正在使用the Google IO talk中所述的BLoC模式。

我有一个简单的BLoC,每当将字符串添加到messageSink时,该BLoC便会在UI中显示警报:

class AlertBloc {
  final _message = BehaviorSubject<String>();

  AlertBloc() {}

  Stream<String> get message => _message.stream;

  Sink<String> get messageSink => _message.sink;

  void dispose() {
    _message.close();   }
}

在应用程序的其他地方,我还有另一个BLoC,当满足特定条件时,该BLoC需要向messageSink添加一个字符串。

我注意到从Google I/O repo for the talk提供整个BLoC并不是一个好主意,他们为将BstrongC的连接到另一个BLoC的接收器提供了建议。 / strong>:

  

请注意,我们向[CartBloc]提供   直接使用[ProductSquareBloc],尽管这样更容易   实行。 BLoC不应该依赖其他BLoC(   关注)。他们只能使用   流。在这种情况下,[CartBloc.items]输出将插入   [ProductSquareBloc.cartItems]输入。

我的问题是如何将接收器从BLoC连接到另一个BLoC

2 个答案:

答案 0 :(得分:1)

与处理流完全相同的方法:将其作为参数传递

class Bloc {
  final Sink<int> _external;

  Bloc(this._external);
}

答案 1 :(得分:1)

这是一个简单的示例。想象以下两个BLoC:

第一个暴露一个Stream并用一些值填充它:

class ProducerBLoC {

    //Controller is private - you do not want to expose it
    final StreamController<int> _productionController = StreamController<int>();
    //Instead, you expose a stream
    Stream<int> get production => _productionController.stream;

    //This method generates some values and puts them to stream
    void produceValue() {
        _productionController.sink.add(1);
        _productionController.sink.add(2);
        _productionController.sink.add(3);
    }

    //Don't forget to close your controllers
    void dispose() {
      _productionController.close();
    }
}

另一个显示Sink并处理放入其中的值。

class ConsumerBLoC {

    //Controller is private - you do not want to expose it
    final StreamController<int> _consumptionController = StreamController<int>();
    //Instead, you expose a sink
    StreamSink<int> get consumption => _consumptionController.sink;

    //In class constructor we start listening to the stream of values
    ConsumerBLoC() {
       _consumptionController.listen((value) {_consumeValue(value);} );
       //or simply: _consumptionController.listen(_consumeValue); //theese are the same
    }

    //This method generates some values and puts them to stream
    void consumeValue(int value) {
         //Do something with the value
         print('Value processed: $value');
    }

    //Don't forget to close your controllers
    void dispose() {
      _consumptionController.close();
    }
}

现在,任务是将生产流连接到消耗接收器。正如您已经正确注意到的那样,您不希望两个BLoC中的任何一个知道有关另一个的存在。因此,两者都不应该保留对另一个实例的引用,甚至不应该创建另一个实例。而是使用Widget类将它们连接起来:

//Define some widget to represent main screen of your application
class MainScreen extends StatefulWidget {

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

//And define a state for this widget (state does not need to be public)
class _MainScreenState extends State<MainScreen> {

    //You define both blocks here
    ProducerBLoC _producer = new ProducerBLoC();
    ConsumerBLoC _consumer = new ConsumerBLoC();

    //Now, either do it in _MainScreenState constructor, or in the initState() method
    @override
    void initState() {
        super.initState();

        //Connect production stream with consumption sink
        _producer.production.listen((value) => _consumer.consumption.add(value));
        //Or, beautifully: _producer.production.pipe(_consumer.consumption);
    }

    @override
    Widget build(BuildContext context) {
        //The exact implementation does not matter in current context
    }

    //And don't forget to close your controllers
    @override
    dispose() {
        super.dispose();
        _producer.dispose();
        _consumer.dispose();
    }

}

这样,ProducerBLoC会立即消耗ConsumerBLoC生成的任何值。而且,最重要的是-两个BLoC彼此完全独立!