首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在没有上下文的情况下使用GoRouter进行路由?

如何在没有上下文的情况下使用GoRouter进行路由?
EN

Stack Overflow用户
提问于 2022-07-21 00:30:23
回答 3查看 2.1K关注 0票数 4

我想解决的问题:使用GoRouter的应用程序需要能够从main()内路由到指定的路由。由于大多数路由都是'context.go‘形式的,所以我不能在main中这样做。

背景

我的应用程序使用GoRouter。GetX让我定义命名的路由并从main()传递参数是非常容易的。

然而,GetX和GoRouter最终给我带来了问题。GoRouter最终将在应用程序的其他部分没有上下文。

如果有办法让它们简单地共存,我就会敞开心扉。

我在GetIt包中使用了服务定位器模式来与navigatorKey相关联。当我测试它时,它会起作用--但这涉及到创建两个MaterialApps。

然而,这个应用程序使用的是GoRouter,它似乎不使用navigatorKey。

我想从main ()内部走一条具体的路线。服务定位器模式似乎可以像在Navigator2.0中用于GoRouter那样适用于MaterialApp --但我找不到如何这样做的示例。

更详细的上下文:

以下是我目前在main()中的内容。

您可以看到我面临的关键挑战是,数据参数的侦听器在主生命中传递(我是从第三方SDK获得的--我不需要它在main中,但是不管应用程序的状态如何,它都需要侦听)。

代码语言:javascript
复制
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;
  });
}

下面是locator.service.dart的样子:

代码语言:javascript
复制
final locator = GetIt.instance;

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

当我可以附加到一个navigatorKey,然后从侦听器中导航时,上面的内容就起作用了。但这似乎不起作用,因为应用程序的其余部分使用GoRouter。

EN

回答 3

Stack Overflow用户

发布于 2022-07-25 10:37:52

不幸的是,如果我是你,我要么放弃使用GetX或GoRouter。

实际上,我会放弃GetX。

原因是GetX在引擎盖下执行了魔法,这提高了开发人员对BuildContext的责任和使用能力,但这显然是一种反模式,因为Flutter内置的导航显然使用了context:例如,想想Navigator.of

GoRouter是围绕context构建的,它简化了执行“Navigator2.0”操作所需的许多实现。

如果您试图实现深度链接,那么您的MaterialApp在根小部件中应该如下所示:

代码语言:javascript
复制
return MaterialApp.router(  // Flutter's Router 2.0 usage
  title: 'MyApp',
  routeInformationProvider: myGoRouter.routeInformationProvider,
  routeInformationParser: myGoRouter.routeInformationParser,
  routerDelegate: myGoRouter.routerDelegate,
);

如果GetX使您能够将myGoRouter放在那里,那么您应该是好的。但正如我前面所说,每次需要显式导航时,都需要上下文。

票数 3
EN

Stack Overflow用户

发布于 2022-09-03 18:03:15

我正在研究在我的项目中采用go_router,而且我也对这个使用过程感到困惑(在我的例子中,我试图证明我可以从appsflyer的回调延迟链接中导航)。

对于解决方案,像这样的go_router允许我们从路由器声明下面的上下文或者从重定向状态导航。因此,我们可以结束所有影响导航的状态。我就是这样从appRouterState重定向的

代码语言:javascript
复制
redirect: (GoRouterState state) {
  String? redirection(GoRouterState state) {
    final appRouterState = ref.read(appRouterStateNotifierProvider);
    final isAuthed = appRouterState.email != null;

    if (appRouterState.deferredLink != state.location && appRouterState.deferredLink != null) {
        return appRouterState.deferredLink;
    }

    if (state.location != '/login' && !isAuthed) return '/login';
    if (state.location == '/login' && isAuthed) return '/';

    return null;
  }
  final result = redirection(state);
  return result;
},

在您的例子中,您可以在setOnReferralDataReceivedListener或其他方面实现appRouterStateProvider。并将其用于refreshListenable构造函数中的GoRouter参数。

希望这能有所帮助。

票数 2
EN

Stack Overflow用户

发布于 2022-09-29 07:47:47

代码语言:javascript
复制
static BuildContext? get ctx => myGoRouter.routerDelegate.navigatorKey.currentContext;

您可以以这种方式在NavigationService中获取上下文,并将其使用如下

代码语言:javascript
复制
NavigationService.ctx?.go(...)

您可能面临的问题是,在应用程序状态下ctx将为空,直到您的第一页开始构建。如果您的侦听器有一个数据,而ctx仍然是空的,则路由将无法工作。但你可以像这样:

在主功能或服务中定义全局tempPageToGo,并且

代码语言:javascript
复制
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(...);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73059450

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档