Streams represent a sequence of asynchronous events. Each event is either a data event, also called an element of the stream, or an error event, which is a notification that something has failed. When a stream has emitted all its events, a single "done" event will notify the listener that the end has been reached. In this lesson, we will learn how we can capture and handle streaming data, working with various Stream classes.
Instructor: [00:00] 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.
[00:13] 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.
[00:29] 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.
[00:51] 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.
[01:18] 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.
[01:38] 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.
[02:01] 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.
[02:17] Using the fromFuture named constructor, we can produce our stream. Let's add our listener, then run.
[02:32] 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.
[02:46] 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.
[03:09] 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.
[03:19] 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.
[03:39] This concludes the lesson.