Using RxDart and Flutter to Create A Timer
Hi Everyone! Very long time without any content š¢ This year, as you can probably imagine, was very hectic. Something had to give, and unfortunately, it was this creative outlet that lost out. Letās jump straight into something completely different!
Iāve been learning Flutter and mobile development, which has been very exciting! Today, I wanted to share with you a little example of a timer app built using Flutter with RxDart as a state management solution. Basically, that means not using the standard setState command in the Stateful Widget.
To kick things off, youāll want to add the latest version of RxDart into your pubspec.yaml file. At the time of writing, this looks like the following:
rxdart: ^0.24.1
In the main.dart file, it can be kept pretty much as a blank slate. Only making sure to replace the home of the Scaffold with a new view. I like to create a separate folder for my āuiā and my āstateā.
Weāll kick off first by looking at the timer_state.dart that will be using RxDart. We need to create a new class, which I will call āTimerStateā. In this new class, we need to create the following variables:
- Private Stopwatch
- BehaviorSubject of type String to track the timer display
- BehaviorSubject of type bool to track whether the timer is running or not
- A string for the initial display value set to ā00:00ā²
- A bool for the initial running state of the timer, set to false
For the class builder, we need to build the two BehaviorSubjects. Weāll do that by creating the following class constructor:
TimerState({this.initialDisplay, this.initialIsRunning}) { _subjectDisplay = BehaviorSubject<String>.seeded(this.initialDisplay); _subjectIsRunning = BehaviorSubject<bool>.seeded(this.initialIsRunning); }
Next, we need to create the two Streams that we can watch for changes to the timer display and whether the timer is running or not. Weāll use these in the UI:
Stream<String> get timerObservable => _subjectDisplay.stream; Stream<bool> get isRunningObservable => _subjectIsRunning.stream;
To finish off the TimerState class, we need to build quite a few functions to help use the timer/stopwatch. Hereās a list below:
- Public function for starting the timer
- Private function for running the timer every second
- Private function for keep the timer running
- Private function for formatting the elapsed time to a minutes/seconds format
- Public function for pausing the timer
- Public function for resetting the timer
- Public function for resuming the timer
- Public dispose function to remove the BehaviorSubjects to avoid memory leaks
For simplicity sakes, here is the full class below:
That is quite a lot to take in, but trust me. Read line by line and test the code yourself and itāll make sense. Break stuff to make stuffā¦
This class and the app, in general, could be a lot simpler. However, I chose to keep the pause, resume and reset options. Only the best content here š
Finally, let's move onto the actual UI š„³
So, we will need a StatefulWidget as we will be creating an instance of the TimerState class which will need disposing of. All the items in my view that needed to change, such as the buttons and the display, were built using the StreamBuilder widget. This is an awesome little widget that listens to a Stream and then changes the output based on a builder function. Here is an example:
Flutter widget trees can get quite confusing to look at, so imma just dump it here for you to look at š¤¦āāļø
Again, that was an absolute steaming dump of code. But test it and itāll make senseā¦
There we go, I hope you can see all of the code goes together. Basically, adding on top of Darts built-in Streams to make them easier to manage and subscribe to š
On top of all the code in the post, here is a link to my GitHub repo with all the code. You might notice a few differences as well.
Enjoy š„³