If I ask you to develop a page that fetches its information as soon as we open it, you’d probably be done in a couple of minutes. You have a variety of hooks to choose for doing the job. Maybe
didChangeDependencies with a control flag, your BLoC’s constructor or anything similar, and they would all work just fine.
But now, what if I ask you to re-fetch the same info whenever the page appears on screen instead of only when it is first opened?
Every Time the Page Appears on Screen?
In other words: every time the page has the focus.
That encompasses three scenarios:
- When we first open it;
- When we come back to it after opening another page;
- When we put the app in the background while the page was on screen, and then bring the app back to the foreground;
Your first impulse will tell you to use the
build method, but that’s a terrible idea because it runs anytime your widget needs to rebuild, and that happens quite a lot.
Then, after spending some time at Google or StackOverflow,
RouteObserver along with
RouteAware widgets will pop at you. It’s a way to register your widget to be notified whenever we push and pop back to its
Route. Problems? It won’t effortlessly work if you use nested
Navigators. Think about it: if you use, for example, a bottom navigation structure, there are two ways in which your page can appear on screen:
- If we push or pop back to its
- If we push or pop back to its “parent widget’s
Route” (the page holding the bottom navigation menu);
To cover the second case, we would have to do all the
RouteAware set up on the parent widget as well and find a way to propagate the event down the tree. If it sounded like a lot of work, that’s because it is! Also, it wouldn’t cover the scenario in which we put the app in the background and then bring it to the foreground again, as the pushed route’s remained the same.
Thankfully, some guys at Google (apparently not from the core Flutter team) provided us a package that gets us closer to what we want.
The VisibilityDetector Package
A VisibilityDetector widget wraps an existing Flutter widget and fires a callback when the widget’s visibility changes.
It looks that now we have everything figured out, right?!
VisibilityDetector won’t detect the case in which we bring the app back to the foreground while the widget was visible.
Fortunately, Flutter does have an easy way for covering that:
WidgetsBindingObserver. We just need to combine it with the
The FocusDetector Package Was Born
From a product perspective, it isn’t the best use case for the
FocusDetector. Re-fetching information every time the page gains the focus isn’t useful at all for an app like this. It only consumes unnecessary bandwidth and makes the app slower.
On the other hand, as far as the code goes, its simplicity is ideal for you to see the
FocusDetector in action.
That’s all! It couldn’t be simpler!
Previously, the above code was calling the
_fetchCharacterSummaryList method on the
initState callback. You can see the initial and final versions by checking out the
focus-detector/set-state-bloc-detector branches, respectively, of the GitHub Repository.
For an example using BLoCs, compare the