Showing the time in the main screen: StreamBuilder

Right now, our main screen never changes, so what we need to do is show the countdown to the user, and also make sure the user can start and stop the timer whenever they need, as follows:

  1. We'll begin by creating the function that will count the work time. For now, we want the work time to be 30 minutes (we’ll make this editable later in this chapter). So, first, in the CountDownTimer class in the timer.dart file, create a field called work and set it to 30. This is the default number of minutes for the work time, and is shown in the following code snippet:
int work = 30;
  1. Next, still in the CountDownTimer class, create a void function that will set the _time duration to the number of minutes contained in the work variable, and the same for the _fullTime field, as follows:
void startWork() {
_radius = 1;
_time = Duration(minutes: this.work, seconds: 0);
_fullTime = _time;
}
  1. The startWork() method should be called from the main screen when it loads. So, let's get back to the main.dart file, and import the timer.dart file, as follows:
import './timer.dart';
  1. Then, at the top of the MyApp class, create a CountDownTimer variable called timer, like this:
final CountDownTimer timer = CountDownTimer();
  1.  At the top of the build() method of MyApp, call the startWork() method, like this:
timer.startWork(); 
  1. Now, we can access the timer properties—time and radius—and show them on the screen: in the CircularPercentIndicator in the Column in the build() method, add the following code: 
 return Expanded(
child: CircularPercentIndicator(
radius: availableWidth / 2,
lineWidth: 10.0,
percent: timer.percent,
center: Text( timer.time,
style: Theme.of(context).textTheme.headline4),
progressColor: Color(0xff009688),
));

If you try the app right now, you should see the timer, but the countdown is not active. That's because we are still missing an important part of the Stream, which is the StreamBuilder. This is what you need to use when you want to listen to events that come from Streams.


A StreamBuilder rebuilds its children at any change in the Stream.

Let's use it in our app, including the Expanded widget into a StreamBuilder, as follows:

  1. We'll set some initialData to have the builder show something while it's waiting for data coming from the stream.
  2. Then, we’ll set the stream itself that we’ve created in the TimerModel class.
  3. Finally, we need to set a builder: this takes a context and a snapshot of type AsyncSnapshot, and the child is what gets rebuilt every time some data comes from the stream. An AsyncSnapshot contains the data of the most recent interaction with a StreamBuilder (or a FutureBuilder).

Wrap the CircularPercentIndicator into a StreamBuilder, as shown in the following code block:

child: StreamBuilder(
initialData: '00:00',
stream: timer.stream(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
TimerModel timer = (snapshot.data == '00:00') ? TimerModel('00:00',
1) : snapshot.data;
return Expanded(
child: CircularPercentIndicator(
radius: availableWidth / 2,
lineWidth: 10.0,
percent: timer.percent,
center: Text( timer.time,
style: Theme.of(context).textTheme.headline4),
progressColor: Color(0xff009688),
));
})),

In the preceding code, note that the snapshot contains a data property: this is what was received from the yield* in the stream() method of the CountDownTimer class, which returned a TimerModel object.

If you try the app right now, the timer should work correctly. However, while the timer is working, the user cannot interact with our app right now. We need to respond when our user taps on one of the buttons. Let's add interactivity to our app next.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.61.170