簡體   English   中英

如何在沒有上下文的情況下在 Flutter 中使用 GoRouter 進行路由?

[英]how can I route using GoRouter in Flutter without context?

我要解決的問題:我使用 GoRouter 的應用程序需要能夠從 main() 中路由到命名路由。 由於大多數路由都是 'context.go' 形式,所以我不能在 main 中這樣做。

背景

我的應用程序使用 GoRouter。 GetX 讓我輕松地定義命名路由並從 main() 傳遞參數是完美的。

然而,GetX 和 GoRouter 最終給我帶來了問題。 GoRouter 最終將在應用程序的其他部分沒有上下文。

如果有一種方法可以讓它們簡單地共存,我願意接受。

我使用服務定位器模式和 GetIt package 來關聯一個導航鍵。 當我測試它時它會工作——但這涉及創建兩個 MaterialApps。

然而,這個應用程序使用的 GoRouter 似乎沒有使用 navigatorKey。

我想從 go 到 main () 內的特定路由。 服務定位器模式似乎適用於 GoRouter,就像它適用於 MaterialApp 的 Navigator 2.0 一樣——但我找不到如何操作的示例。

更詳細的上下文:

這是我目前在 main() 中的內容。

您可以看到我面臨的主要挑戰是,傳入的數據參數的偵聽器存在於 main 中(我從第三方 SDK 獲得了它——我不需要它位於 main 中,但無論如何它都需要監聽應用程序的 state)。

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 的樣子:

final locator = GetIt.instance;

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

當我可以附加到 navigatorKey 然后從偵聽器中導航時,上面的方法有效。 但這似乎不起作用,因為應用程序的 rest 使用 GoRouter。

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

您可以通過這種方式在 NavigationService 中獲取上下文並像這樣使用它

NavigationService.ctx?.go(...)

您可能面臨的問題是,在您的第一個頁面開始構建之前,ctx 將在應用程序 state 上為 null。 如果您的偵聽器有數據而 ctx 仍為 null,則路由將不起作用。 但你可以像這樣處理這種情況:

在主要功能或服務中定義全局tempPageToGo

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(...);

不幸的是,如果我是你,我會放棄使用 GetX 或 GoRouter。

實際上,我只是放棄 GetX。

原因是 GetX 在幕后執行了魔法,提升了開發人員的責任和BuildContext的使用,但這顯然是一種反模式,因為 Flutter 的內置導航清楚地使用了context :例如,想想Navigator.of

GoRouter是圍繞context構建的,並簡化了執行“Navigator 2.0”操作所需的許多實現。

如果您嘗試實現深度鏈接,您的MaterialApp在您的根小部件中應如下所示:

return MaterialApp.router(  // Flutter's Router 2.0 usage
  title: 'MyApp',
  routeInformationProvider: myGoRouter.routeInformationProvider,
  routeInformationParser: myGoRouter.routeInformationParser,
  routerDelegate: myGoRouter.routerDelegate,
);

如果 GetX 允許您將myGoRouter放在那里,那么您應該對 go 很好。 但正如我之前所說,每次需要顯式導航時,都需要上下文。

我正在研究在我的項目中采用 go_router ,並且我也被這個用例所困擾(在我的情況下,我試圖證明我可以從來自appsflyer SDK 回調的延遲鏈接導航)。

對於解決方案,go_router 允許我們從位於路由器聲明下方的上下文或從重定向 state 導航。 所以我們可以總結所有影響導航的 state。 這就是我從 appRouterState 重定向的方式

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;
},

在您的情況下,您可以在 appRouterStateProvider 或其他東西中實現setOnReferralDataReceivedListener 並將其用於refreshListenable構造函數中的GoRouter參數。

希望這可以幫助。

我發現在沒有上下文的情況下使用 go_router 並不容易,但在routemaster中很容易

閱讀更多:https://pub.dev/packages/routemaster#navigate-without-a-context

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM