In this part, we will have a look on flutter’s approach towards implementing animations, especially what flutter offers to be able to get new instance of elapsed time as and when elapsed time changes since when the animations starts.
In Introduction to Animation Curves, we concluded with the two things which are elapsed time and curve, that we need to be able to satisfy human eyes that there’s an actual animation taking place.
To the human eye, film and video would seem to be playing as one continuous recording. But what happens is quite different, cameras record pictures of multiple images, called frames.
These frames are played back at such a fast rate that they appear to be in fluid motion. Frame rate is the measurement of how quickly several frames appear within a second, which is why it’s also called FPS (frames per second).
Consider the following gif.
Consider the pages of the book to be different frames which when played or being changed at a very fast rate, human eyes get a feel of some movement in the objects over time as and when a new frame appears with updated properties of the same object.
With every new frame, the position of the boy changes which makes our human eyes feel like everything else is static and it’s just the boy who is getting separated away from his family.
UI frameworks try to do nothing different than what we can see in the above gif when it comes to updating the state of objects on the screen.
To animate an object on a UI screen, or just simply update the state of an object on a UI screen, pretty much every UI framework, in its way, tries to achieve the same by scheduling the changes to be made on the object (using setState in flutter or useState in react), which will be executed during the next render of the frame by the underlying rendering engine being which the UI framework uses.
Thus, any simple state updates on an object or widget through calls to setState are not immediately executed but are just scheduled to be executed in the next scheduled frame only.
It might seem to our human eyes that the updates are immediately being executed because we would see the immediate reflection of our setState calls on the screen. But behind the scenes, it all happens only during the next scheduled frame.
It depends on how fast the next frame is being rendered by the rendering engine. This is determined by the frame rate or FPS of the rendering engine used by the underlying UI framework being used. Flutter engine uses a scheduler that renders the new frames at the rate of 60 frames in a second (60fps).
After getting a brief idea of frames, it becomes easier to understand how state updates take place behind the scenes. In addition to that, it opens up our minds to how we could achieve our goal to update the properties of the widget periodically as and when elapsed time changes.
In the case of animation, we can’t simply go with just the setState because, to schedule a state update, we need to be sure about what should the updated state value be, to be able to pass it in the setState.
In the case of animation, the updated value of the widget’s property is not known just like that because it depends on how much time has elapsed since when the animation started.
In Flutter, one would be tempted to go with Timer.periodic to be able to get the value of elapsed time.
The Timer.periodic approach might seem correct but is not performant. Moreover, the value of elapsed time that we get always depends on the arbitrary period value which we pass to Timer.periodic constructor, which is of Duration(milliseconds: 50) in the above example.
Thus, even though we can compute the value of elapsed time, it is only after a period of every 50 milliseconds in our case. And suppose you use a periodicity of 1000 milliseconds, it will be only after every 1 second you would get a new value of elapsed time to then update the UI state. Thus, more is the more periodicity we choose, the slower will be the changes in the UI and the human eyes would not be satisfied with such changes and won’t consider them as animation.
Instead, a more performant approach we would want to go with, especially after knowing the fact that Flutter renders 60 frames per second, which is blazing fast, would be what if we get to know whenever Flutter renders a new frame!
Well, you are working with Flutter after all! That should have been obvious by now!
Flutter has exactly what you need and is specifically dedicated to this very purpose, which is to subscribe whenever Flutter renders a new frame.
Flutter offers Ticker API which is designed especially to be able to get notified whenever Flutter’s engine is about to draw a new frame which would be one of those 60 frames in a second. This means you would be notified 60 times every second, and you need not bother setting up a periodic timer just for this.
The best part is, it also gives you a fresh instance of elapsed time since the ticker has started, whenever it notifies about the new frame, which is exactly what we have been looking for after all!
Getting notified on every new frame is the key feature driving flutter animations.
Ticker is a class in Flutter’s scheduler.dart library, which takes in a callback and calls it once per every new frame.
Flutter also offers another interface TickerProvider, which can be used to create an instance of Ticker and thus get notified on every new frame being triggered.
The most commonly used implementers of TickerProvider are the following two mixins:
To create an instance of Ticker from within your flutter widget, you would want to make your widget a StatefulWidget, to begin with, and then mix in your state class with either one of these two mixins.
TickerProvider has a method createTicker which takes in the callback which is invoked on every new frame and is invoked with elapsed time duration.
As you can see we got one step closer to what we need to implement animations in Flutter because we figured out a way to keep on getting a fresh new instance of elapsed time as and when Flutter’s underlying rendering engine renders a new frame.
This step was the most challenging one to achieve when it comes to implementation, and Flutter does it well. The entire Flutter animations framework uses Ticker API under the hood.
Now, we are left with one last step which is to use different curve functions which would take in the obtained fresh new instance of elapsed time and return the widget’s property which should be applied when this particular duration of time has elapsed. I will cover this in the next part of this series.