I have an app. Its homepage has a lot of functionality(heaver). It takes a little bit time to build. Therefore when App starts I show the Splash screen in the meantime Homepage is built. But when I navigate(by push replacement) from the homepage to another it's dispose method called. So when I try to come back to the homepage it takes some time and the app got hang for that time. So I want that When I navigate(by push replacement) from Homepage to another page its dispose method should not be called. So, when user want to come back to the homepage it doesn't rebuild.
Note: I can not use Navigator.push or something else except push replacement because I am navigating from navigation bar( I made my custom Navigation Bar Where I cannot use anything else except push replacement).
Related
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 when
Internal 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 when
Internal 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.
Best Pick
FocusDetector (Edson Bueno)
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
Isn’t maintained by Flutter or Google (but it uses VisibilityDetector and WigetBindingObserver under the hood)
The default VisibilityDetectorController.updateInterval is 500ms which means the events get fired somewhat late.
Borrowing the style from one of my favorite posts:
Example Widget
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'),
);
}
}
Other options
RouteObserver (Flutter)
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:
Doesn’t cover use-case (2), backgrounding then foregrounding the app
WidgetsBindingObserver (Flutter)
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:
Isn’t widget/route specific (for external nav (2))
Doesn’t cover use-case (1), navigating between pages
VisibilityDetector (Google)
onVisibilityChanged (visibility == 1) = onResume
onVisibilityChanged (visibility == 0) = onPause
Cons:
Doesn’t cover use-case (2), backgrounding then foregrounding the app
flutter
Is the back button the same as dispose() method ?
I know there's not much similarity, but I mean, when you hit the back button, does that free up memory from the tree of the page we left?
Considering that you're talking about the Framework's BackButton widget, then eventually, why?
Because the framework's back button is just an abstraction of creating your own widget with an IconButton that calls Navigator.maybePop(context); when it is pressed.
To answer your question: yes, if the page is closed when BackButton is pressed, then yes it will release resources (it will call dispose() if your widget is a stateful widget).
Keep in mind that your still need to override the dispose() method and release any resource (if any) so that those resources are release when the back button is pressed.
To sum up::: BackButton simply calls Navigator.maybePop(context); and it will only release resources of your StatefulWidget IF you overrode it AND call some_class.dispose().
No the back button doesn't replace the dispose function if you have controllers in a statefulwidget screen when state object is removed you will need to dispose it to avoid memory leaks.
flutterdartmethodscallbackdispose
I am creating an app that has multiple questions (like a quiz) and I am using Getx for state management.
in the main method I initialize controllers as follows
void main() {
Get.put(HomeScreenController());
Get.put(QuestionsController());
runApp(MyApp());
}
in the home screen I have a pageview and I am using HomeScreenController() to manage it.
The last page of the page view has a button to go back to the initial page. For my case, I want to reset all variables in both controllers to their initial values.
I have tried one solution, it worked but I feel like it is tedious to do for other controllers that has so many variables which is calling a method that reset the variables manually.
The other solution that I have tried is to dispose the controllers when the user clicks on the button calling Get.put(HomeScreenController()); in the build method of the home screen.
onPressed: () {
qCon.dispose();
controller.dispose();
Navigator.pushReplacementNamed(context, HomeWrapper.id);
},
but I got an error that says
A HomeScreenController was used after being disposed.
'Once you have called dispose() on a HomeScreenController, it can no longer be used.
is there anyway to do what I am trying to do other than updating variable manually?
Update: Turns out that
Get.reset();
do the job when initializing controllers in the home screen
also calling
Get.put(ControllerName());
in a build method will re-initialize the controller
I'm currently developing an app which uses ads.
I've created an Adbanner for testing in the main view.
In the main view i have a lot of buttons that send the user to other routes. Most of this buttons are in another classes and used elsewhere inside the app. I know that to dismiss or dispose the banner i just need to call Dispose() or Dismiss().
My problem is that i'm lookin for a way to dismiss or dispose the bannerAd on the Navigator.push()
I found this and this that doesnt answer my question.
Thanks in advance to anyone who can help
initState seems to be called every time the screen it belongs to is shown. Is there a method that is called only once during the time the app is open?