Tim*_*thy 13 service-locator flutter gorouter
我想解决的问题: 我使用 GoRouter 的应用程序需要能够从 main() 内路由到命名路由。由于大多数路由都是“context.go”形式,因此我无法在 main 中执行此操作。
背景
我的应用程序使用 GoRouter。GetX 让我轻松定义命名路由并从 main() 传递参数,这非常完美。
然而,GetX 和 GoRouter 最终给我带来了问题。GoRouter 最终在应用程序的其他部分将没有上下文。
如果有一种方法可以让它们简单地共存,我会对此持开放态度。
我使用了 GetIt 包的服务定位器模式来与 navigatorKey 关联。当我测试它时它会起作用 - 但这涉及创建两个 MaterialApp。
然而,这个应用程序使用GoRouter,它似乎没有使用navigatorKey。
我想从 main() 内部转到特定的路线。服务定位器模式似乎适用于 GoRouter,就像适用于 MaterialApp 的 Navigator 2.0 一样——但我找不到如何执行此操作的示例。
更详细的上下文:
这是我目前在 main() 中的内容。
你可以看到我面临的关键挑战是在 main 中传递数据参数的监听器(我从第三方 SDK 得到这个——我不需要它在 main 中,但无论如何它都需要监听应用程序的状态)。
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;
});
}
Run Code Online (Sandbox Code Playgroud)
这是 locator.service.dart 的样子:
final locator = GetIt.instance;
class NavigationService {
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
// final GlobalKey<ScaffoldMessengerState> navigatorKey = GlobalKey<ScaffoldMessengerState>();
}
Run Code Online (Sandbox Code Playgroud)
当我可以附加到 navigatorKey 然后从侦听器内导航时,上述方法有效。但这似乎不起作用,因为应用程序的其余部分使用 GoRouter。
小智 14
static BuildContext? get ctx => myGoRouter.routerDelegate.navigatorKey.currentContext;
Run Code Online (Sandbox Code Playgroud)
您可以通过这种方式在您的 NavigationService 中获取上下文并像这样使用它
NavigationService.ctx?.go(...)
Run Code Online (Sandbox Code Playgroud)
您可能面临的问题是 ctx 在应用程序状态下将为空,直到您的第一个页面开始构建。如果您的侦听器有数据而 ctx 仍为空,则路由将不起作用。但你可以像这样处理这种情况:
在 main func 或服务中定义一个全局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(...);
Run Code Online (Sandbox Code Playgroud)
小智 12
我们可以使用路由器对象在没有上下文的情况下进行导航。
final router= GoRouter(....);
Run Code Online (Sandbox Code Playgroud)
现在导航使用,
router.push(...);
Run Code Online (Sandbox Code Playgroud)
不幸的是,如果我是你,我要么放弃使用 GetX,要么放弃使用 GoRouter。
事实上,我会放弃 GetX。
原因是 GetX 在幕后发挥了魔力,提高了开发人员的责任和使用 的能力BuildContext
,但这显然是一种反模式,因为 Flutter 的内置导航明确使用context
: think of 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,
);
Run Code Online (Sandbox Code Playgroud)
如果 GetX 允许您将其放在myGoRouter
那里,那么您就可以开始了。但正如我之前所说,每次您需要显式导航时,您都需要上下文。
归档时间: |
|
查看次数: |
14094 次 |
最近记录: |