【问题描述】:

关于 Flutter 的 Google I/O 2018 video 解释了如何使用 Dart 流来管理 Flutter 应用程序中的状态。演讲者谈到了使用Sink作为输入流和Stream作为输出流。 SinkStream 有什么区别?我搜索了文档,但没有说太多谢谢。

【问题讨论】:

    标签: stream dart flutter


    【解答1】:

    SinkStream 都是 StreamController 的一部分。您可以使用 SinkStreamController 添加数据,该数据可以通过 Stream 进行监听。

    例子:

    final _user = StreamController<User>();
    Sink get updateUser => _user.sink;
    Stream<User> get user => _user.stream;
    

    用法:

    updateUser.add(yourUserObject); // This will add data to the stream.
    

    每当通过 sink 将数据添加到流中时,它都会被发出,可以使用 listen 方法进行监听。

    user.listen((user) => print(user)); 
    

    您可以在发出流之前执行多种操作。 transform 方法是一个示例,可用于在输入数据发出之前对其进行转换。

    【问题讨论】:

    【解答2】:

    如果您正在寻找关于流和接收器的非常基本的定义,请参考:

    - 传送带被称为流

    StreamController - 这是控制流的东西

    StreamTransformer - 这是处理输入数据的部分

    StreamBuilder - 这是一种将流作为输入的方法,并为我们提供了一个构建器,该构建器在每次流有新值时都会重新构建

    sink - 接受输入的属性

    stream - 从 Stream 中提供输出的属性

    更多详情,please refer to this article

    【问题讨论】:

      【解答3】:

      一个 StreamSink 是一个 StreamConsumer,这意味着它可以接收多个流(由addStream 添加)并处理这些流发出的事件。

      如果它是 StreamControllerStreamSink,则添加的流中的所有事件都由 StreamController 创建的流发出。< /p>

      通过这种方式,您可以通过管道(转发)一个或多个流到另一个流。

      【问题讨论】:

      • 这里不是在解释streams和sink的区别,而是在谈论如何使用它们。
      • 你如何解释没有共同点的事物的不同之处?它们是可以一起使用的两种不同的东西,所以“有什么区别”并没有真正的意义。
      • 我认为最好解释一下它们每个是什么,以及它们的用途。当我自己开始 dart 时,我很难理解 Sink 是什么。
      • 所以如果我不需要做任何处理,我就不需要使用 Sink。我说的对吗?
      • 换种说法:sink 是对可以放入数据的事物的抽象。它没有说明数据的用途。在许多情况下,您不需要创建接收器,您只需将值直接传递给需要它的函数,但有时您想概括一下。例如,StringSink 是由 StringBufferHttpResponse 实现的接口,因为您可以将字符串写入它们两者。同理,StreamSinkStreamControllerHttpResponse 都实现的接口,因为您可以向两者添加流。
      【解答4】:

      让我们举一个 Flutter 中 SINKS & STREAMS 的简单示例。请阅读cmets

             class LoginBloc {
                final _repository = Repository();
                final _loginResponse = BehaviorSubject<bool>();  //---->> a simple Sink
                Stream<bool> get isSuccessful => _loginResponse.stream; //-----> Stream linked with above sink
      
              /*
             *  Below is an async function which uses Repository class
             *  to hit a login API and gets the result in a variable
             *  isUserLoginSuccessful[true/false]. and then Add the result 
             *  into the sink.
             *  now whenever something is added to the sink, a callback is given to
             *  the stream linked to that Sink, which is managed by the framework itself 
             *  
             */
      
               Future getLoginResponse() async { 
                  bool isUserLoginSuccessful = await _repository.processUserLogin();
                  _loginResponse.sink.add(isUserLoginSuccessful);
                }
      
                dispose() {
                  _loginResponse.close();
                }
              }
      

      现在,我在登录屏幕中使用了这个 LoginBloc。

           class Login extends StatelessWidget {
            final LoginBloc loginBloc;  // ----> Here is the Object of LoginBloc
            Login(this.loginBloc);
      
            void _onClickLoginButton() async {
              // Hit login API
              // fetch Login API response data
              loginBloc.getLoginResponse(); //------> here is the function we are using in Login
            }
      
            @override
            Widget build(BuildContext context) {
              return StreamBuilder<bool>(    // ----> You need to use a StreamBuilder Widget on the top Root, or according to the Business logic
                stream: loginBloc.isSuccessful,   // ----> here is the stream which is triggered by Sink which is linked by this stream
                builder: (context, snapshot) {
              // DO WHATEVER YOU WANT AFTER CALLBACK TO STREAM
      });
      

      我希望这可以使您的流和接收器概念更加清晰。

      【问题讨论】:

      • _loginResponse.sink.add(isUserLoginSuccessful); 有什么区别?和 _loginResponse.add(isUserLoginSuccessful); ?