Instructor: Streams represent a sequence of data events that occur while reading information from a data source. Streams are especially used when dealing with data sources like HTML events emitted from button clicks or reading data from a file.
To demonstrate the concept of streams, we will use the StreamController interface. This will help us handle streaming data as well as invoke events by feeding data into the controller. The stream is exposed through the stream property, which contains the listen method for handling streaming data.
To invoke a data event, use the add method to feed data to the stream. Let's run this example. A StreamController is also a generic class, which means that we can specify the type of data we expect to be handled in the stream. We can also listen for errors and done events on the stream.
To invoke the onError handler, use the addError method. To invoke the onDone handler, use the close method. Calling the close event also returns a future, meaning we can add a then callback method. Let's refactor with async/await syntax.
There are two types of streams in Dart, single subscription and broadcast streams. The example we've seen so far is a single subscription stream. This means that we can only attach a single stream listener event. Attempting to add another listener will throw a run-time error.
With a broadcast stream, we can implement more than one listener. To create one, invoke the asBroadcastStream method. Let's write some listeners and feed some data to them.
We can also use async/await syntax to listen for streaming data. Streams can be created from generic types such as futures. To demonstrate, let's create a future.
Using the fromFuture named constructor, we can produce our stream. Let's add our listener, then run.
We can also implement basic error-handling by defining an onError handler. Let's trigger this error by using a wrong endpoint. We can also add a list of futures to the stream.
To demonstrate, let's add another API call that returns a future. Using the fromFutures named constructor, pass a list containing both futures, and listen for the result.
Streams can also be created from iterable types, like list or set. Here is an example of a stream produced from a list using the fromIterable named constructor.
Then we will listen for each character fed to the stream. Let's run. One useful application of this would be simulating a typing effect using a timer.
This concludes the lesson.