I am new to Flutter.
I have three classes, the first one is the Home Screen and the second one is from the SDK that is used to call the API through a function in the third class.
I want to go to the second screen from the Home Screen and there I have to call the API function from the third class.
After calling the API, I have to come back to the second screen where I am waiting for the response. I have to pass this response to the Home Screen.
After calling the API function, I will take the user to the Home Screen immediately.
I have to get the response at the Home Screen after the API will return it.
ApiMethods is in the third class and apiRequest is its function that is calling and returning the response of the API.
ApiMethods().apiRequest().then((response) {
//controller will come here after getting response
//here should be a callback that will take response to homeScreen
});
//going immediately back to home screen after calling API
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => userHome),
(route) => false);
You can use Navigator.popAndPushNamed(context, userHome).
Related
According to this blog, if using Navigator 2.0 and/or (in my case) GoRouter you can no longer override the phone's back button using the "WillPopScope" and onWillPop function call. Navigator 2.0 now uses PopRoute to go back.
This causes an issue when using webview on a flutter page. If the user navigates to another web page within that webview and then clicks the back button on their phone they naturally expect the webview navigate back to the previous web page. But instead it takes the user off that page and back to their previous flutter page.
Is there any way around this? Can I have my back button first check whether there is a controller.canGoBack() like I used to be able to do with the old Navigator system?
I have found a solution. Convoluted, but functional:
I had to create a custom "backButtonDispatcher" and add it to the main.dart MaterialApp.router function
child: Builder(builder: (BuildContext context) {
final router = Provider.of<MainRouter>(context, listen: false).router;
backbuttondispatcher = backButtonDispatcher(router.routerDelegate, settings);
return MaterialApp.router(
routeInformationParser: router.routeInformationParser,
routeInformationProvider: router.routeInformationProvider,
routerDelegate: router.routerDelegate,
backButtonDispatcher: backbuttondispatcher,
.
.
.
I created the new dispatcher in the router folder and called it "backbuttondispatcher.dart.
import 'package:flutter/material.dart';
class backButtonDispatcher extends RootBackButtonDispatcher {
final RouterDelegate _routerDelegate;
final _settings;
backButtonDispatcher(this._routerDelegate,this._settings)
: super();
Future<bool> didPopRoute() async {
//Can user leave the page?
if (!_settings.canLeavePage) {
//no, as the webview widget has flagged canLeavePage as false
_settings.goBackToPreviousWebsite();
return true;
}else{
//yes, perform standard popRoute call
return _routerDelegate.popRoute();
}
}
}
Using a shared class reference (I used "_settings") I store a flag that says whether or not the user has traversed through more than one web page - if TRUE, the back button dispatcher won't go back to a previous route/page and instead call another function (pointer) that handles going back to a previous web page in the webview widget route. But if FALSE, the dispatcher performs it's standard didPopRoute function.
Additionally, on all other routes/pages with a webview, the pointer function and boolean need to reset to null and false. This is not ideal but fortunately there aren't that many pages in the app.
It annoys me that they changed the back button functionality for main route/page navigation but didn't take in to consideration the fact that the back button can also be used for going back to a previous webpage. I understand that we shouldn't really be showing web pages with apps anyway but we lowly developers don't always have the power to deny app requirements from higher up.
This is my App's flow:
How do I update the Home Page when I press back and return to it from the MaterialPageRoute? I attempted to use the setState method in the dispose() method of MaterialPageRoute, but it gave me an error.
You can use Navigator.push(context,MaterialPageRoute(builder: (context) => TheSecondPage())).then((value) { setState(() {}); thus when you pop from TheSecondPage() you will immediatelly call the setState refreshing the page.
Actually, the Home Page is automatically updated, however I made a mistake by updating the variable within the dispose() method, which is invoked after the Home Page has been updated.
When I insert data from other page and pop this page to go back on the listing page, I have to refresh the listing page to get the updated list of data. I want to go back to the updated version of page without pressing refresh button. I am using pushNamed and also I want to have a back arrow button on the input page.
Using Navigator.push or Navigator.pushNamed returns a Future object to you.
This Future resolves when you use Navigator.pop in the your second screen.
Here is a basic example. Assuming you have function goToNewPage which you are calling to push a new Screen, you can do it like this.
class Screen1State extends State<Screen1> {
void goToNewPage (context) {
Navigator.of(context).pushNamed('screen2').then((_) {
// The screen2 has popped. so you can just call setState here to just rebuild
// You can do anything you want here, that needs to happen after the new page has been popped.
setState(() {});
});
}
... rest of your code.
Note, the actual implementation of what you should do inside the callback depends on how your widget is getting data. But you can do anything you want to do after your new page is popped inside that callback.
Below is my app widget tree. If user is not logged in then login page is shown if user is logged in then work page. on account page I have logout button.Logout button implements push replacement and shows login page.
Issue is - When user click on back button again work page is shown.
How to remove all the routes from widget tree and only show login page after logout action?
Note - I am not using Named routes, just Push , Pop and Replacement
If you are using namedRoutes, you can do this by simply :
Navigator.pushNamedAndRemoveUntil(context, "/login", (Route<dynamic> route) => false);
Where "/login" is the route you want to push on the route stack.
Note That :
This statement removes all the routes in the stack and makes the pushed one the root.
Close your dialog by calling,
Navigator.pop(context);
and then call pushReplacement
void _doOpenPage() {
navigator.pushReplacement(
MaterialPageRoute(builder: (BuildContext context) => MyHomePage()));
}
pushReplacement Replace the current route of the navigator by pushing the given route and then disposing the previous route once the new route has finished animating in.
Read More here
I have a page which is calling multiple classes and different widgets
and by clicking on it user can hop to any page.
Currently the issue is I want to refresh the original page everytime it is shown to user.
When it is freshly loaded (causing no issue for now).
When user comes back to it from some other page using back key.
old data is shown on the page, which I am trying to get rid of.
I have tried using Navigator.push method (Observer class method) and tried to listen when user presses backkey.
but there are multiple pages serving unique requests and I don't want to link everyone with that first page.
as while clicking Navigator.pop(context) method i'll have to pass some string.
Does any one know
how can I refresh the page when users comes back to it using backkey.
Navigator.push returns a Future when the MaterialPageRoute passed into it is resolved. You could await that Future to know when some other view has popped back to it.
Example,
Navigator.of(context).push(MaterialPageRoute(
builder:
(context) => NewView(),
),
).then((_) {
// Call setState() here or handle this appropriately
});
Had the same issue, the following worked for me (below code is in FirstPage()):
Navigator.push( context, MaterialPageRoute( builder: (context) => SecondPage()), ).then((value) => setState(() {}));
After you pop back from SecondPage() to FirstPage() the "then" statement will run and refresh the page.
NavigatorObserver can listen to route changes.
You need to create your implementation overriding didPop, didPush etc.
Then you can pass it to navigatorObservers field of MaterialApp or Navigator