4.4 动态与嵌套路由

张开发
2026/4/12 15:02:21 15 分钟阅读

分享文章

4.4 动态与嵌套路由
动态路由处理 Tab/BottomNavigationBar 等多层导航场景深链Deep Linking则打通 App 与外部系统的连接。一、Tab / BottomNavigationBar 场景1.1 保持各 Tab 状态IndexedStackclassMainPageextendsStatefulWidget{overrideStateMainPagecreateState()_MainPageState();}class_MainPageStateextendsStateMainPage{int _currentIndex0;// 各 Tab 的 Navigator Key独立路由栈finalListGlobalKeyNavigatorState_navigatorKeys[GlobalKeyNavigatorState(),GlobalKeyNavigatorState(),GlobalKeyNavigatorState(),];overrideWidgetbuild(BuildContextcontext){returnScaffold(body:IndexedStack(// 保留所有 Tab 状态index:_currentIndex,children:[_TabNavigator(navigatorKey:_navigatorKeys[0],initialRoute:/home),_TabNavigator(navigatorKey:_navigatorKeys[1],initialRoute:/explore),_TabNavigator(navigatorKey:_navigatorKeys[2],initialRoute:/profile),],),bottomNavigationBar:BottomNavigationBar(currentIndex:_currentIndex,onTap:(index){if(index_currentIndex){// 双击 Tab回到该 Tab 根页面_navigatorKeys[index].currentState?.popUntil((r)r.isFirst);}else{setState(()_currentIndexindex);}},items:const[BottomNavigationBarItem(icon:Icon(Icons.home),label:首页),BottomNavigationBarItem(icon:Icon(Icons.explore),label:发现),BottomNavigationBarItem(icon:Icon(Icons.person),label:我的),],),);}// 处理 Android 物理返回键Futurebool_onWillPop()async{finalcanPop_navigatorKeys[_currentIndex].currentState?.canPop()??false;if(canPop){_navigatorKeys[_currentIndex].currentState?.pop();returnfalse;}returntrue;// 允许退出 App}}class_TabNavigatorextendsStatelessWidget{finalGlobalKeyNavigatorStatenavigatorKey;finalStringinitialRoute;const_TabNavigator({requiredthis.navigatorKey,requiredthis.initialRoute});overrideWidgetbuild(BuildContextcontext){returnNavigator(key:navigatorKey,initialRoute:initialRoute,onGenerateRoute:AppRouter.generateRoute,);}}1.2 使用 GoRouter 的 StatefulShellRoutefinalrouterGoRouter(routes:[StatefulShellRoute.indexedStack(builder:(context,state,navigationShell){returnMainScaffold(navigationShell:navigationShell);},branches:[StatefulShellBranch(routes:[GoRoute(path:/home,builder:(_,__)constHomePage(),routes:[GoRoute(path:article/:id,builder:(_,state)ArticlePage(id:state.pathParameters[id]!,),),],),],),StatefulShellBranch(routes:[GoRoute(path:/explore,builder:(_,__)constExplorePage()),],),StatefulShellBranch(initialLocation:/profile,routes:[GoRoute(path:/profile,builder:(_,__)constProfilePage()),],),],),],);classMainScaffoldextendsStatelessWidget{finalStatefulNavigationShellnavigationShell;constMainScaffold({super.key,requiredthis.navigationShell});overrideWidgetbuild(BuildContextcontext){returnScaffold(body:navigationShell,// 自动管理各 Branch 状态bottomNavigationBar:NavigationBar(selectedIndex:navigationShell.currentIndex,onDestinationSelected:(index){navigationShell.goBranch(index,// 双击 Tab 回到根initialLocation:indexnavigationShell.currentIndex,);},destinations:const[NavigationDestination(icon:Icon(Icons.home),label:首页),NavigationDestination(icon:Icon(Icons.explore),label:发现),NavigationDestination(icon:Icon(Icons.person),label:我的),],),);}}二、WebView 嵌套场景// 在 Tab 内部推入 WebView不影响底部导航GoRoute(path:/home,builder:(_,__)constHomePage(),routes:[GoRoute(path:webview,builder:(_,state){finalurlUri.decodeComponent(state.uri.queryParameters[url]!);returnAppWebViewPage(url:url);},),],)// 打开 WebViewcontext.push(/home/webview?url${Uri.encodeComponent(https://example.com)});三、深链Deep Linking3.1 配置 Android 深链android/app/src/main/AndroidManifest.xmlactivityintent-filterandroid:autoVerifytrueactionandroid:nameandroid.intent.action.VIEW/categoryandroid:nameandroid.intent.category.DEFAULT/categoryandroid:nameandroid.intent.category.BROWSABLE/!-- 自定义 Schememyapp://product/42 --dataandroid:schememyappandroid:hostproduct/!-- HTTPS 深链https://example.com/product/42 --dataandroid:schemehttpsandroid:hostexample.com//intent-filter/activity3.2 配置 iOS 深链ios/Runner/Info.plistURL SchemeskeyCFBundleURLTypes/keyarraydictkeyCFBundleURLSchemes/keyarraystringmyapp/string/array/dict/arrayUniversal Linksios/Runner/Runner.entitlementskeycom.apple.developer.associated-domains/keyarraystringapplinks:example.com/string/array3.3 uni_links监听深链dependencies:uni_links:^0.5.1classDeepLinkHandlerextendsStatefulWidget{finalWidgetchild;constDeepLinkHandler({super.key,requiredthis.child});overrideStateDeepLinkHandlercreateState()_DeepLinkHandlerState();}class_DeepLinkHandlerStateextendsStateDeepLinkHandler{StreamSubscription?_linkSub;overridevoidinitState(){super.initState();_initDeepLink();}Futurevoid_initDeepLink()async{// 处理冷启动时的深链App 未在运行try{finalinitialUriawaitgetInitialUri();if(initialUri!null)_handleDeepLink(initialUri);}catch(e){debugPrint(Deep link error:$e);}// 处理热启动时的深链App 在后台_linkSuburiLinkStream.listen((uri){if(uri!null)_handleDeepLink(uri);},onError:(e)debugPrint(Deep link stream error:$e),);}void_handleDeepLink(Uriuri){// myapp://product/42// https://example.com/product/42switch(uri.pathSegments.first){caseproduct:finaliduri.pathSegments.last;router.push(/product/$id);break;casecategory:router.push(/category/${uri.pathSegments.last});break;caseshare:finalcodeuri.queryParameters[code];router.push(/share?code$code);break;}}overridevoiddispose(){_linkSub?.cancel();super.dispose();}overrideWidgetbuild(BuildContextcontext)widget.child;}3.4 GoRouter 原生深链支持GoRouter 对深链有原生支持只需配置路由即可finalrouterGoRouter(// GoRouter 自动解析 Deep Linkroutes:[GoRoute(path:/product/:id,builder:...),],);// Flutter 配置pubspec.yaml// flutter:// deeplinking:// enabled: true小结场景推荐方案Tab 保持状态IndexedStack 独立NavigatorGoRouter TabStatefulShellRoute.indexedStack深链Schemauni_links 手动解析深链URLGoRouter 原生支持双击 Tab 回根popUntil(isFirst)或goBranch(initialLocation: true) 下一章五、网络与数据

更多文章