What is the difference between Sink and Stream in Flutter?
Asked Answered
Y

4

40

The Google I/O 2018 video about Flutter explains how to use Dart streams to manage state in a Flutter application. The speaker talked about using Sink as input stream and Stream as output stream. What is the difference between Sink and Stream? I searched the documentation but it doesn't say too much thanks.

Yahwistic answered 15/5, 2018 at 12:28 Comment(0)
R
21

A StreamSink is a StreamConsumer, which means it can take several streams (added by addStream) and processes the events these streams emit.

If it is the StreamSink of a StreamController then all events from the added streams are emitted by the stream created by the StreamController.

This way you can pipe (forward) one or more streams into another one.

Ronrona answered 15/5, 2018 at 12:35 Comment(6)
This is not explaining the difference between streams and sink, but instead talking about how to use them.Shuttle
How do you explain the difference of something that has nothing in common? They are 2 different things that can be used together, so "what is the difference" doesn't really make sense.Octaviooctavius
I think it would be better to explain what each of them are, and what they are used for. when I myself started dart, I had a hard time understanding what a Sink was at all.Shuttle
So if I don't need to do any processing, I wouldn't need to use a Sink. Am I right?Yahwistic
A sink is an event consumer. If you want to specify and API that is able to consume a stream, then you express that by exposing an sink property. If you don't need that, then you don't. Actually I have never used a sink myself yet and I wrote quite a bit of Dart already. If found the video inspiring, but still didn't encounter a use case for a sink in my code.Octaviooctavius
Said another way: A sink is an abstraction over something that you can put data into. It doesn't say what the data is used for. In many cases, you don't need to create a sink, you just pass a value directly to the function needing it, but sometimes you want to generalize. For example, a StringSink is an interface implemented both by StringBuffer and HttpResponse because you can write strings to them both. In the same way, a StreamSink is an interface implemented both by StreamController and HttpResponse, because you can add streams to both.Cotto
W
86

Sink and Stream both are parts of the StreamController. You add a data to the StreamController using Sink which can be listened via the Stream.

Example:

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

Usage:

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

Whenever a data is added to the stream via sink, it will be emitted which can be listened using the listen method.

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

You can perform a various number of actions before the stream is emitted. transform method is an example which can be used to transform the input data before it gets emitted.

Wizard answered 22/9, 2018 at 15:41 Comment(3)
I have asked another question about the relationships btw BehaviorSubject, StreamController and Sink: stackoverflow.com/questions/53349073, can you please have a look? Thanks a lot.Podiatry
Is there any difference between streamController.sink.add() and streamController.add() ?Corrales
Nothing. Check this answer for more details. https://mcmap.net/q/333977/-what-is-the-difference-between-streamcontroller-add-and-streamcontroller-sink-addWizard
R
21

A StreamSink is a StreamConsumer, which means it can take several streams (added by addStream) and processes the events these streams emit.

If it is the StreamSink of a StreamController then all events from the added streams are emitted by the stream created by the StreamController.

This way you can pipe (forward) one or more streams into another one.

Ronrona answered 15/5, 2018 at 12:35 Comment(6)
This is not explaining the difference between streams and sink, but instead talking about how to use them.Shuttle
How do you explain the difference of something that has nothing in common? They are 2 different things that can be used together, so "what is the difference" doesn't really make sense.Octaviooctavius
I think it would be better to explain what each of them are, and what they are used for. when I myself started dart, I had a hard time understanding what a Sink was at all.Shuttle
So if I don't need to do any processing, I wouldn't need to use a Sink. Am I right?Yahwistic
A sink is an event consumer. If you want to specify and API that is able to consume a stream, then you express that by exposing an sink property. If you don't need that, then you don't. Actually I have never used a sink myself yet and I wrote quite a bit of Dart already. If found the video inspiring, but still didn't encounter a use case for a sink in my code.Octaviooctavius
Said another way: A sink is an abstraction over something that you can put data into. It doesn't say what the data is used for. In many cases, you don't need to create a sink, you just pass a value directly to the function needing it, but sometimes you want to generalize. For example, a StringSink is an interface implemented both by StringBuffer and HttpResponse because you can write strings to them both. In the same way, a StreamSink is an interface implemented both by StreamController and HttpResponse, because you can add streams to both.Cotto
M
17

If you are looking for a very basic definitions on stream and sinks, then refer to this:

Stream - the conveyor belt is called as a stream

StreamController - this is what controls the stream

StreamTransformer - this is what processes the input data

StreamBuilder - it’s a method that takes stream as an input and provides us with a builder which rebuilds every time there is a new value of a stream

sink - the property which takes an input

stream - the property which gives the output out of the Stream

For more details, please refer to this article

Montespan answered 5/11, 2019 at 9:23 Comment(0)
A
1

Let us take a simple example of SINKS & STREAMS in Flutter. Please Reade the comments

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

Now, I am using this LoginBloc in Login Screen.

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

i hope this may make your stream & sink concept more clearer.

Aubervilliers answered 19/3, 2019 at 11:22 Comment(3)
what is the difference between _loginResponse.sink.add(isUserLoginSuccessful); and _loginResponse.add(isUserLoginSuccessful); ?Deposit
@Deposit This might answer your question.Frayda
Thank you. It get's me point of truth.Deposit

© 2022 - 2024 — McMap. All rights reserved.