В чем разница между Sink и Stream в Flutter?

В видеоролике Google I/O 2018 о Flutter объясняется, как использовать потоки Dart для управления состоянием в приложении Flutter. Докладчик говорил об использовании Sink качестве входного потока и Stream качестве выходного потока. В чем разница между Sink и Stream? Я искал документацию, но это не говорит, что большое спасибо.

Ответ 1

StreamSink - это StreamConsumer, что означает, что он может принимать несколько потоков (добавленных addStream) и обрабатывать события, которые испускают эти потоки.

Если это StreamSink StreamController то все события из добавленных потоков отправляются потоком, созданным StreamController.

Таким образом, вы можете направить (переслать) один или несколько потоков в другой.

Ответ 2

Я попытаюсь объяснить на простом примере, потому что с этого момента это легко понять.

Sink и Streams являются частью контроллера потока. Вы добавляете данные в контроллер потока, используя sink который можно прослушивать через 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.
  user.listen((user) => print(user)); // Whenever a data is added to the stream via sink, it will be emitted which can be listened using the listen method.

Вы можете выполнить различное количество действий, прежде чем поток будет выпущен. Метод transform - это пример, который можно использовать для преобразования входных данных до того, как они будут получены.

Ответ 3

Давайте возьмем простой пример РАКОВИНЫ И ПОТОКА во Флаттере. Пожалуйста, прочитайте комментарии

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

Я надеюсь, что это может сделать вашу концепцию потока и стока более ясной.