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.
问题:
回答1:
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.
回答2:
I will try to explain with a simple example because from that point it is easy to understand.
Sink
and Streams
are both part of the stream controller. You add a data to the stream controller 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.
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.
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.
回答3:
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.
回答4:
If you are looking for a very basic definitions on stream and sinks, then refer 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,pls refer the following article: