flutter call a function after moving back to screen from another screen - flutter

How to call a function in flutter ,after moving back to a screen from another screen?
For Example:
Screen 1
function1(){
}
Screen2
function2(){
//Go back to screen 1 and then call function1()
}

It's simple.
Navigator.push(context, MaterialPageRoute(builder: (context)=> SecondScreen())).then((_){
// This method gets callback after your SecondScreen is popped from the stack or finished.
function1();
});
You should also refer the Flutter Navigation & Routing.

Here is the solution!
Second Screen
Navigator.pop(context, [1]);
or, if you don't want to send back any data, you can only call
Navigator.pop(context);
First Screen
Navigator.push( context, MaterialPageRoute( builder: (context) => SecondScreen(), ), ).then((value) { //do something after resuming screen
});

Imho the solutions provided here aren't valid solutions.
If you use a routes Future it may be called multiple times and will even be called in case of a forward navigation.
Instead use a NavigatorObserver:
class AppNavigationObserver extends NavigatorObserver {
#override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
print("AppNavigationObserver: ${route.settings.name}");
print("AppNavigationObserver: ${previousRoute?.settings.name}");
}
}
You can then use it for example like this:
MaterialApp(
navigatorObservers: [
AppNavigationObserver()
],
onGenerateRoute: (RouteSettings settings) {
return PageRouteBuilder(
maintainState: true,
settings: settings,
transitionDuration: const Duration(milliseconds: 300),
pageBuilder: (context, animation, secondaryAnimation) {
// Your route builder according to settings
},
);
},
)
The important part is passing onGenerateRoute's settings paramter to the PageRouteBuilder settings. Otherwise settings.arguments and settings.name will be null in the didPop handler.

Related

Flutter how to open page from push notification, context issue

void selectNotification(String? payload) async {
print('Selected notification');
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SearchScreen(),
),
);
}
I am using this method to open a screen when the notification is tapped, I get the print message fine but then the Navigator message shows:
The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
Im just trying to have it so if the notificaiton is tapped from foreground, background where ever the app then just pops open that screen but I cant get it to work
void selectNotification(String? payload, BuildContext context) async {
print('Selected notification');
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SearchScreen(),
),
);
}
Use getX package and use navigation routing:
something like this:
Get.put(()=> **your page**
getX package

Call a method on page pop

I'm pushing a new route like so in my app
Navigator.of(context)
.push<void>(
FilterTypesPage.routeFullScreen(context),
).then(
(value) {
log('PAGGGE POPPED');
},
),
static Route routeFullScreen(BuildContext context) {
return MaterialPageRoute<void>(
settings: const RouteSettings(name: routeName),
builder: (_) => BlocProvider.value(
value: BlocProvider.of<FeatureBloc>(context),
child: const FilterTypesPage(),
),
fullscreenDialog: true);
}
for some reason log('PAGGGE POPPED'); doesn't get called on page close
I'd like to trigger a bloc event or a function when I close this page
You should just call
Navigator.pop(context, someData);
from your RouteSettings where someData is the data you want to pass from the RouteSettings to the former page.
Then from your former page, you can perform your event handling inside the then block. The value inside the then block is the data that was passed from the RouteSettings page.
Alternatively, you can also use async-await instead of then in your former page.
onPressed: () async {
final someData = await Navigator.of(cotext).push(.....);
// Now perform your event handling which will be invoked after you pop `RouteSettings` page.
}

refresh previous page on Navigator.pop function

Is there any way to refresh the previous page/ stack when Navigator.pop(context) is called? I need to do the API calling of the previous page to refresh the state of the page. The navigator.pop will sometimes be an alert dialog or maybe a back button. Is there a way to do the API calling? ThankYou.
use the then function after you push another route.
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => MyHomePage(),
),
).then(
(value) {
if (value) {
//refresh here
}
},
);
and when you return to previous screen, provide the pop function a value that determines whether to perform some action.
Navigator.of(context).pop(true);
Previous page
void goToNextPage()async {
var refresh = await Navigator.push(_context, new MaterialPageRoute(
builder: (BuildContext context) => new nextPage(context))
);
if(refresh ) setState((){});
}
NextPage
Navigator.pop(context, true);

Flutter: How to perform an actions after Navigator.pushNamedAndRemoveUntil() has completed

In my Flutter app, I need to clear the Navigator stack and get back to the Home page when a certain button is pressed. To achieve that I've used Navigator.pushNamedAndRemoveUntil(context, "/", (r) => false);. I also need to call a function after the navigation has been completed, meaning that I'm now on the Home page.
I've tried calling the .whenComplete() method on Navigator.pushNamedAndRemoveUntil(), but it doesn't seem to work.
Thanks in advance.
I'd say use your function inside dipose(), so it's called when the widget is removed from the tree as you navigate to another screen.
class _MyPageState extends State<MyPage> {
// ...
// Some code
#override
void dispose() {
// Insert your function here
super.dispose();
}
// ...
}
Using didPush() method
This can be used to call your function after navigating to another screen because it returns when the push transition is complete. However, you have to do it with pushAndRemoveUntil() instead of pushNamedAndRemoveUntil(). So, you can create a PageRoute which provides didPush() method.
// Create your route
MaterialPageRoute route = MaterialPageRoute(
builder: (context) => HomePage(),
);
// Push the route onto the navigator, and then remove all the previous routes
Navigator.pushAndRemoveUntil(context, route, (r) => false);
// This returns when the push transition is complete.
route.didPush().whenComplete(() {
// Insert your function here
});
You can try as well as this code And please let me know.
gotoNewPage(context) async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
NewPage()));
/// Your logic is here.
}

Flutter :- How manage the backstack like in Android "SingleTask"?

I am trying to manage the backstack in Flutter like in Android we manage it from launchMode (eg. SingleTask,SingleTop , Standard etc..) , For it i have tried the Routes in flutter, but did not get the success, please check the below code, which i have tried to achieve the backstack.
Widget makeRoute(
{#required BuildContext context,
#required String routeName,
Object arguments}) {
final Widget child =
_buildRoute(context: context, routeName: routeName, arguments: arguments);
return child;
}
Widget _buildRoute({
#required BuildContext context,
#required String routeName,
Object arguments,
}) {
switch (routeName) {
case '/':
return SplashScreen();
case '/A': //// NAME OF SCREEN IS A
return A();
case '/B': //// NAME OF SCREEN IS B
MyBean docs = arguments as MyBean;
return B(dataToShow: docs);
case '/C': //// NAME OF SCREEN IS C
MyBean docs = arguments as MyBean;
return C(dataToShow: docs);
case '/D': //// NAME OF SCREEN IS D
return D();
}
}
I am jumping the screens from A->B->C->D are as follow,
From A->B , I navigate it like below.
Navigator.of(context).pushNamed('/B');
From B->C , I navigate it like below.
Navigator.of(context).pushNamed('/C', arguments: myList[index]);
And finally, From C->D , I navigate it like below.
Navigator.of(context).pushNamed('/D');
As from the above code, I successfully navigated to the A------>D screens and also carrying data successfully.
But my main concern is that i want to navigate from the D->A or D->B screen using the backstack without opening another screen, So i have tried the below code but it is not working , please check the below code.
From D->A, I have tried like
Navigator.popUntil(context, ModalRoute.withName('/A'));
And even tried in this manner like below.
Navigator.of(context)
.popUntil(ModalRoute.withName("/A"));
I even this way to manage the flow like below
SchedulerBinding.instance.addPostFrameCallback((_) {
Navigator.popUntil(context, ModalRoute.withName('/A'));
});
But both are not working properly
Please check my main() class
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: '',
theme: ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.grey,
primaryColor: ColorConst.PRIMARY_COLOR,
accentColor: ColorConst.ACCENT_COLOR,
primaryColorBrightness: Brightness.light,
accentColorBrightness: Brightness.light,
),
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute(
builder: (BuildContext context) => makeRoute(
context: context,
routeName: settings.name,
arguments: settings.arguments,
),
maintainState: true,
fullscreenDialog: false,
);
}
)
);
}
And getting the following exception from above code like below.
═ (2) Exception caught by widgets library ═══════════════════════════════════════════════════
'package:flutter/src/widgets/navigator.dart': Failed assertion: line 2330 pos 12: '!_debugLocked': is not true.
The relevant error-causing widget was:
MaterialApp **file:///Users/apple/Documents/BitBucket%20Projects/loyalityapp_android/lib/main.dart:10:7**
════════════════════════════════════════════════════════════════════════════════════════════════════
If you are using the following code to pop until the route "/A" using Navigator.popUntil method then you should have to set your opening screen with the help of "initialRoute" property in your MaterialApp Widget instead of "home" property.
Navigator.popUntil(context, ModalRoute.withName('/A'));
Because, here you are navigating to the route "A" with the help of "push navigator routes" and want to pop using "named routes"
Also, you can set it with "/" route in your routes property as Follow,
initialRoute : "A",
OR
routes:{
"/": (context)=> A(),
}
Every thing other is fine in your code.
I have solved the problem by using the MaterialPageRoute and referred this link to get the solution Click here
From A->B->C->D screen navigation, I have used this approach
From A->B screen
Navigator.push(
context,
MaterialPageRoute(
settings: RouteSettings(name: "B"),
builder: (context) => SCREEN_B(),
),
);
And from B->C, I haved used this along with parameters like below
Navigator.push(
context,
MaterialPageRoute(
settings: RouteSettings(name: "C"),
builder: (context) => SCREEN_C(dataToShow:myList[index]),
),
);
From C->D screen
Navigator.push(
context,
MaterialPageRoute(
settings: RouteSettings(name: "D"),
builder: (context) => SCREEN_D(),
),
);
And main logic is here navigations from D->A or D->B, from below liens of code
Navigator.popUntil(context, ModalRoute.withName("A")); //YOU CAN USE "B" TO NAVIGATE
At the last one more thing which I need to add here is that when I want to perform any action like refresh activity and anything else from screen D->A
Then inside the A screen, we need to use then method like below
Navigator.push(
context,
MaterialPageRoute(
settings: RouteSettings(
name: "B"),
builder: (context) =>
B(dataToShow: MYLIST[index]),
),
).then((value) {
//// THIS METHOD IS ENVOKE WHEN SCREEN COME FROM D->A OR B->A, YOU CAN PERFROM CAN TASK HERE
});