簡體   English   中英

將BLoC的接收器與另一個BLoC連接

[英]Connecting a sink of BLoC with another BLoC

我正在使用Google IO演講中所述的BLoC模式。

我有一個簡單的BLoC,它用於在向messageSink添加字符串時在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倉庫中提供整個BLoC並不是一個好主意,他們為將從BLoC連接到另一個BLoC接收提供了建議:

請注意,盡管我們更容易實現,但我們並未直接將[CartBloc]提供給[ProductSquareBloc]。 BLoC不應該依賴其他BLoC(關注點分離)。 他們只能使用流彼此通信。 在這種情況下,[CartBloc.items]輸出插入到[ProductSquareBloc.cartItems]輸入中。

我的問題是如何將接收從BLoC連接到另一個BLoC

這是一個簡單的示例。 想象以下兩個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中的任何一個都知道另一個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彼此完全獨立!

與使用流完全相同的方法:將其作為參數傳遞

class Bloc {
  final Sink<int> _external;

  Bloc(this._external);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM