Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Flutter Web - Fix Refresh & Back button Problem
swimmingkiim
swimmingkiim

Posted on • Edited on

     

Flutter Web - Fix Refresh & Back button Problem

Image description

Update Notice!!!

The explaination below is somewhat outdated. Now, I recommends you to usego_router, a routing package using Flutter Navigation 2.0!

Intro

When I’m on a flutter web, I faced with routing issue. BothMaterialApp andGetMaterialApp had the same issues, which was routing acts weird when browser’s back button and refresh button are clicked. So I’ve tried some test project with flutter web and I found the solution. Now, it works just like native web project. I’d like to share this solution with you.

Flutter Navigation 2.0

There is this thing calledFlutter Navigation 2.0 . I didn’t dig much about it, but to simply put, it’s navigation system is now more customizable with this Navigation 2.0.

Since the original routing system had so many problems in web platform, I had to try this one. And it worked, thankfully. You can use withMaterialApp.router instead of justMaterialApp . But if you do that you need to implement some override method which involves in navigation logic. Instead overriding each methods, I usedGetMaterialApp.router which comes with default methods, and therefore, only extra thing to do is just build method.

Code Implementation

Install Getx

At this moment, I used below version ofGetx package.

dependencies:...get:^4.6.1
Enter fullscreen modeExit fullscreen mode

Basic Routing Stuff

For convenience, I used simple routing path and getPages with snippet.

abstractclassRoutes{staticconstHOME='/';staticconstLOGIN='/login';staticconstSIGNUP='/signup';}
Enter fullscreen modeExit fullscreen mode
abstractclassAppPages{staticfinalpages=[GetPage(name:Routes.HOME,page:()=>Home(),),GetPage(name:Routes.LOGIN,page:()=>Login(),),GetPage(name:Routes.SIGNUP,page:()=>Signup(),),];}
Enter fullscreen modeExit fullscreen mode

CreateGetMaterialApp.router

When you useGetMaterialApp.router instead of justGetMaterialApp , you don’t need to provide(and you can’t)initialRoute . But you need to providegetPages androuterDelegate fields with values.

import'package:flutter/material.dart';import'package:get/get.dart';voidmain(){runApp(GetMaterialApp.router(debugShowCheckedModeBanner:false,defaultTransition:Transition.fade,getPages:AppPages.pages,routerDelegate:AppRouterDelegate(),));}
Enter fullscreen modeExit fullscreen mode

Create Sample Pages

For testing, I created some simple test pages with different background colors.

  • Note that when you navigate between pages, you need to useGet.rootDelegate instead ofGet because we’re usingrouterDelegate to handle routing.
classHomeextendsStatelessWidget{constHome({Key?key}):super(key:key);@overrideWidgetbuild(BuildContextcontext){returnContainer(color:Colors.red,child:TextButton(child:Text('Home',style:TextStyle(color:Colors.white),),onPressed:()=>Get.rootDelegate.toNamed(Routes.LOGIN),),);}}classLoginextendsStatelessWidget{constLogin({Key?key}):super(key:key);@overrideWidgetbuild(BuildContextcontext){returnContainer(color:Colors.orange,child:TextButton(child:Text('Login',style:TextStyle(color:Colors.white),),onPressed:()=>Get.rootDelegate.toNamed(Routes.SIGNUP),),);}}classSignupextendsStatelessWidget{constSignup({Key?key}):super(key:key);@overrideWidgetbuild(BuildContextcontext){returnContainer(color:Colors.blue,child:TextButton(child:Text('Signup',style:TextStyle(color:Colors.white),),onPressed:()=>Get.rootDelegate.toNamed(Routes.HOME),),);}}
Enter fullscreen modeExit fullscreen mode

Create router delegate withGetDelegate

So, this is the main part.

  • CreateAppRouterDelegate or what ever you like to call withGetDelegate extended.
  • Overridebuild method and returnNavigator withonPopPage andpages .
    • onPopPage → This is invoked when pop action happened, and return wheather pop is successful or not. If you don’t want to block pop action, just leave it there with default code.
    • pages → This is different fromgetPages . This is more related to what page to show in current moment. I’m not fully figured out yet, but it’s also different from navigation history stack. So, in order to show the right page according to current url, I usedcurrentConfiguration.currentPage . Note that this field can’t be empty since it related to current view. WhencurrentConfiguration is null(which means first entered the page), you can just simply return initial page.
classAppRouterDelegateextendsGetDelegate{@overrideWidgetbuild(BuildContextcontext){returnNavigator(onPopPage:(route,result)=>route.didPop(result),pages:currentConfiguration!=null?[currentConfiguration!.currentPage!]:[GetNavConfig.fromRoute(Routes.HOME)!.currentPage!],);}}
Enter fullscreen modeExit fullscreen mode

And plus, since you can writebuild method and other override method(if you want to customize login) you can easily add user authentication status check before navigate to any page.

Conclusion

I think Flutter Web has a long way to go, but I’m glad Flutter is keeping up there work! I hope this article can help those who struggles with Flutter Web routing issue.

Cheers!

Buy Me A Coffee

Top comments(22)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
korca0220 profile image
ParkJuneWoo
  • Joined

Hello!! This article was really helpful! Thank you
But how did you handle it likeGet.back()? An error occurs in this process. Same asGet.rootDelegate.popRoute().

I would ultimately like to implement the following elements.

  1. Go back, go forward after refresh in a web browser. -> Success
  2. Widgets that return to the previous page when the<- button is pressed (previously useGet.back())
CollapseExpand
 
swimmingkiim profile image
swimmingkiim
Currently working on an open source project: react-image-editor -> https://github.com/swimmingkiim/react-image-editorYou can support me: https://www.buymeacoffee.com/swimmingkiim
  • Location
    Seoul, South Korea
  • Education
    Univ
  • Pronouns
    She / Her
  • Work
    Indie Developer
  • Joined

You can do that by usingGet.roodDelegate.popHistory with custom logic.

  1. First, overridepopHistory method inAppRouterDelegate
classAppRouterDelegateextendsGetDelegate{GetNavConfiggetprevRoute=>// herehistory.length<2?history.last:history[history.length-2];@overrideFuture<GetNavConfig>popHistory()async{// and herefinalresult=prevRoute;Get.rootDelegate.offNamed(prevRoute.currentPage!.name);returnresult;}@overrideWidgetbuild(BuildContextcontext){returnNavigator(......);}}
Enter fullscreen modeExit fullscreen mode
  1. And call it like this
Get.rootDelegate.popHistory();
Enter fullscreen modeExit fullscreen mode

I've tested it and it works for me. Hope this can help you :-)

CollapseExpand
 
korca0220 profile image
ParkJuneWoo
  • Joined

Thank you!! That was really helpful

If you refresh it, it doesn't workpopHistory, but I think we can solve it in a different way!

Thread Thread
 
shambhulky profile image
shambhulky
  • Joined
• Edited on• Edited

How you have implemented this? Even without overriding, getting same result.

CollapseExpand
 
kkimj profile image
Jiun Kim
  • Joined
• Edited on• Edited

Hello!
We can go back via html API, dart:html

// importimport'dart:html'ashtml;{// within callBack// ..html.window.history.back();}
Enter fullscreen modeExit fullscreen mode

Thanks!
HANW!

CollapseExpand
 
kkimj profile image
Jiun Kim
  • Joined

Helloo Buddies~

CollapseExpand
 
everfinal88 profile image
Paul Lam
  • Joined

Hi, thanks for the article. I tested the code and found out the browser back history did not really get back to the previous page state. For example when i scroll to certain location and navigate back again, instead of getting back new page was loaded. Is there any way we can preserve the page state using your code?

CollapseExpand
 
swimmingkiim profile image
swimmingkiim
Currently working on an open source project: react-image-editor -> https://github.com/swimmingkiim/react-image-editorYou can support me: https://www.buymeacoffee.com/swimmingkiim
  • Location
    Seoul, South Korea
  • Education
    Univ
  • Pronouns
    She / Her
  • Work
    Indie Developer
  • Joined

Yes, I also found some issue of that approach. As of now, the simplest way to solve this problem is using@kkimj 's method. (window.history.back()) If you want to manually manage your history stack, then check outpushHistory method in Delegete class. Maybe you can cache those records and write your own back method logic.

CollapseExpand
 
disterbia profile image
disterbia
  • Joined

when i did it your way on the flutter web,Get.rootDelegate.toNamed("/") works, butGet.rootDelegate.offToNamed("/") throws an Unexpected null value error. I think there is an error related to the key, but I can't figure it out.
AlsoGet.snackbar() throws the same error.

CollapseExpand
 
8138976373 profile image
Safvan Puthalath
  • Joined

class AppRouterDelegate extends GetDelegate {
@override
Widget build(BuildContext context) {
return Navigator(
key: Get.key, //Please add this line to get snackbar,dialog,etc.
onPopPage: (route, result) => route.didPop(result),
pages: currentConfiguration != null
? [currentConfiguration!.currentPage!]
: [GetNavConfig.fromRoute(Routes.HOME)!.currentPage!],
);
}
}

CollapseExpand
 
disterbia profile image
disterbia
  • Joined
CollapseExpand
 
verrelravanelli profile image
verrelravanelli
  • Joined

Hey, i tried to open your stackoverflow link but its say already removed. Do you already find the solution for this problem? Thanks

CollapseExpand
 
imanyarahmadi profile image
iManYarahmadi
  • Joined

hi my friends i use this article for my app route but im using this code on flutter web and when refresh or back,forward button in browser clicked nothing happend in my app.. how can handle this ?
my code like this

class AppRouterDelegate extends GetDelegate {
GetNavConfig get prevRoute => // here
history.length < 2 ? history.last : history[history.length - 2];

@override
Future popHistory() async {
// and here
final result = prevRoute;
Get.rootDelegate.offNamed(prevRoute.currentPage!.name);
return result;
}

@override
Widget build(BuildContext context) {
GlobalKey mainNavigatorKey = GlobalKey();

return Navigator(  key: mainNavigatorKey,  onPopPage: (route, result) => route.didPop(result),  pages: currentConfiguration != null      ? [currentConfiguration!.currentPage!]      : [GetNavConfig.fromRoute(Routes.LOGIN)!.currentPage!],);
Enter fullscreen modeExit fullscreen mode

}
}

CollapseExpand
 
woywie87 profile image
woywie87
  • Joined

Hi, It was very helpful. But I realized that with this fix, WillPopScope widget (or new PopScope) don't work (Flutter Web)
Case like this:

  1. Go to new page by "Get.rootDelegate.toNamed(Routes.SecondPage)"
  2. Press back button - onWillPop in SecondPage method never fired :/
CollapseExpand
 
_mohamed_mab profile image
Mohamed Elbendary
Software Engineer, Flutter developer, (MaB)
  • Location
    Egypt
  • Work
    Software Engineer
  • Joined
• Edited on• Edited

Hello !! the solution of overridingpopHistory() not working, I can't go back to the previous page on mobile, is there any solution can handle it likeGet.back() but in navigator 2.0

CollapseExpand
 
wuwang profile image
huho
  • Joined

@swimmingkiim why you recommend to user go_router?

CollapseExpand
 
kyoshio profile image
Kyo
  • Joined

Hello, how do I make Getx compatible with Go router? My project depends heavily on GetX. How can I quickly migrate to go router

CollapseExpand
 
raj_vaghasiya_c22fd5ee132 profile image
Raj Vaghasiya
  • Joined

have you found any solution?
i have same problem. please let me know

CollapseExpand
 
suisui profile image
SuiSui
  • Joined

Yes, you can mix GetX pages and GoRouter.
Like this sample.

Future<void> main() async {  usePathUrlStrategy();  GoRouter.optionURLReflectsImperativeAPIs = true;  var router = GoRouter(navigatorKey: Get.key, initialLocation: '/', routes: [    GoRoute(      name: 'home',      path: '/',      builder: (context, state) => YourHomePage(),    ),    GoRoute(      name: 'page2',      path: '/page2',      builder: (context, state) => YourPage2(),    )  ]);  runApp(GetMaterialApp.router(    debugShowCheckedModeBanner: false,    routeInformationParser: router.routeInformationParser,    routerDelegate: router.routerDelegate,    routeInformationProvider: router.routeInformationProvider,    builder: (BuildContext context, Widget? child) {      return child ?? Container();    },  ));}.....static toPage2() {    BuildContext? context = Get.context;    if(context==null) return;    context.pushNamed('page2');  }
Enter fullscreen modeExit fullscreen mode
CollapseExpand
 
shambhulky profile image
shambhulky
  • Joined

How to logout ? After logout, still going to previous page on back press.
How to go home from login so that login page will not open when we press back button ?

CollapseExpand
 
impatelravi profile image
Ravi Patel
  • Joined

Try with arguments. It's not working. As it use root where no arguments are passed.

CollapseExpand
 
danhquyen0109 profile image
danhquyen0109
  • Joined

You can try:

Get.rootDelegate.arguments()

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Currently working on an open source project: react-image-editor -> https://github.com/swimmingkiim/react-image-editorYou can support me: https://www.buymeacoffee.com/swimmingkiim
  • Location
    Seoul, South Korea
  • Education
    Univ
  • Pronouns
    She / Her
  • Work
    Indie Developer
  • Joined

More fromswimmingkiim

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp