Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how can I route using GoRouter in Flutter without context?

The problem I want to solve: My app which uses GoRouter needs to be able to route to a named route from within main(). Since most routing is of the form 'context.go' I cannot do so within main.

Background

My app uses GoRouter. The ease with which GetX had let me define named routes and pass parameters from main() was perfect.

However, GetX and GoRouter eventually causes problems for me. GoRouter would eventually have no context in other parts of the app.

If there were a way to have them co-exist simply, I'd be open to it.

I had used the service locator pattern with the GetIt package to associate with a navigatorKey. It would work when I tested it -- but this involved creating two MaterialApps.

However, this app uses GoRouter which doesn't seem to use the navigatorKey.

I would like to go to a specific route from within main (). It seems like the service locator pattern could work for GoRouter as it did with Navigator 2.0 for MaterialApp -- but I can't find an example of how to do so.

More detailed context:

Here is what I have currently in main().

You can see the key challenge I have is that the listener for the data parameters being passed in lives in main (I got this from the third-party SDK -- I don't need it to be in main but it needs to listen regardless of the state of the app).

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  FFAppState(); // Initialize FFAppState

  GetSocial.addOnInitializedListener(() => {
        // GetSocial SDK is ready to use
      });

  setupLocator();

  runApp(MyApp());

  locator<LandingPageData>().referralID = "defaultReferralID";

  registerListeners();
}

void registerListeners() {
  Invites.setOnReferralDataReceivedListener((received) {
    globalReferralData = received;
    print(globalReferralData);
    print(globalReferralData.linkParams);

    print("listener - socialdata");

    String passedReferralID =
        globalReferralData.linkParams['referralID'].toString();
    String passedCreatorID =
        globalReferralData.linkParams['creatorID'].toString();
    String passedCampaignID =
        globalReferralData.linkParams['\$campaign_id'].toString();

    print(passedReferralID);
    print(passedCreatorID);
    print(passedCampaignID);

    // How can I route to a named Route?

    locator<LandingPageData>().referralID = passedReferralID;
    locator<LandingPageData>().creatorID = passedCreatorID;
    locator<LandingPageData>().campaignID = passedCampaignID;
  });
}

Here is what the locator.service.dart looks like:

final locator = GetIt.instance;

class NavigationService {
  final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
  // final GlobalKey<ScaffoldMessengerState> navigatorKey = GlobalKey<ScaffoldMessengerState>();
}

The above worked when I could attach to a navigatorKey and then navigate from within the listener. But that doesn't seem to work since the rest of the application uses GoRouter.

like image 899
satchel Avatar asked Dec 21 '25 13:12

satchel


2 Answers

we can use the router object to navigate without context.

final router= GoRouter(....);

now to navigate use,

router.push(...);
like image 71
tk_tanz Avatar answered Dec 23 '25 08:12

tk_tanz


static BuildContext? get ctx => myGoRouter.routerDelegate.navigatorKey.currentContext;

you can get context in your NavigationService in this way and use it like

NavigationService.ctx?.go(...)

the problem you may face is that ctx will be null on app state till your first page starts to be built. In the case your listener has a data while ctx is still null, routing won't work. but you can handle this situation like:

define a global tempPageToGo in main func or a service and

var _ctx = NavigationService.ctx;
if(_ctx == null) {
  tempPageToGo = anyPageDataYouWant;
  while((await Future.delayed(Duration(seconds: 1))) == null) {
    if(_ctx != null) {
      _ctx!.go(...);
      break;
    }
  }
} else _ctx!.go(...);
like image 44
fmdogan Avatar answered Dec 23 '25 06:12

fmdogan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!