I've seen this asked before, but the questions are always subsets of functionality. I'm looking for exact equivalent life cycle events. And I can be more specific.
The ones I'm aware that exist in Flutter widgets are
onCreate
/viewDidLoad
= initState
onDestroy
/viewDidUnload
= dispose
These are the life cycle events I'd like to know about (for the currently visible widget/route, not the entire app):
onResume
/ viewWillAppear
getting fired on the currently visible widget whenInternal nav (navigating around within the app)
a. You push the route/widget onto the stack
b. You navigate back to the route/widget (that was already on the back of nav stack)
External nav (backgrounding and foregrounding the app)
a. You open the app from the background (and the route/widget is the one being displayed to the user)
b. You turn the screen on (power button) and the app was already open
onPause
/ viewDidDisappear
getting fired on the currently visible widget whenInternal nav (navigating around within the app)
a. You navigate away from a widget/route going forward
b. You navigate away from the widget by dismissing it / going backward in the stack
External nav (backgrounding and foregrounding the app)
a. You background the app (and the route/widget is the one being displayed to the user) b. You turn the screen off (power button) with the app open
I've found a few solutions, each with its own pros and cons. The one that answers this question the best is FocusDetector.
FocusDetector handles all the cases covered in the original question. Instead of overrides (like initState() and dispose()), you supply callback functions to a wrapping widget called FocusDetector
. The two relevant callbacks are:
onFocusGained
= onResume
onFocusLost
= onPause
Cons
VisibilityDetector
and WigetBindingObserver
under the hood)VisibilityDetectorController.updateInterval
is 500ms which means the events get fired somewhat late.Borrowing the style from one of my favorite posts:
class PageState extends State<Page> {
@override
void initState() {
super.initState();
log("onCreate / viewDidLoad / initState");
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
layoutComplete();
});
}
// Bonus one I've found helpful, once layout is finished
void layoutComplete() {
log("onActivityCreated / viewDidLoad / layoutComplete");
}
void viewWillAppear() {
log("onResume / viewWillAppear / onFocusGained");
}
void viewWillDisappear() {
log("onPause / viewWillDisappear / onFocusLost");
}
@override
void dispose() {
log("onDestroy / viewDidUnload / dispose");
super.dispose();
}
@override
Widget build(BuildContext context) {
return FocusDetector(
onFocusGained: viewWillAppear,
onFocusLost: viewWillDisappear,
child: Text('Rest of my widget'),
);
}
}
didPush
= onResume
current screen is pushed on
didPopNext
= onResume
current screen is being navigated back to
didPop
= onPause
dismissing current page / going back
didPushNext
= onPause
navigating forward to a new page
Cons:
AppLifecycleState.resumed
= The app is visible and responding to user input
AppLifecycleState.paused
= The app is not visible and not responding to user input
Cons:
onVisibilityChanged
(visibility == 1) = onResume
onVisibilityChanged
(visibility == 0) = onPause
Cons: