網站首頁 編程語言 正文
1.Navigator使用簡介
使用Flutter 的Navigator
導航器可以實現頁面的跳轉,Navigator
的使用方法簡單介紹一下:
頁面跳轉:
Navigator.push<void>( context, MaterialPageRoute( builder: (BuildContext context) => const MyHomePage(), ), );
頁面跳轉的同時關閉當前頁面(頁面替換):
Navigator.pushReplacement<void, void>( context, MaterialPageRoute( builder: (BuildContext context) => const MyHomePage(), ), );
頁面跳轉的同時關閉到之前的某一個頁面:
Navigator.pushAndRemoveUntil<void>( context, MaterialPageRoute( builder: (BuildContext context) => const MyHomePage(), ), (route) => false // ModalRoute.withName('/') );
也可以直接使用路由名稱進行上面操作,例如跳轉:Navigator.pushNamed(context, '/home');
路由名稱需要提前在MaterialApp
中定義好。
MaterialApp( title: 'Flutter Demo', home: MyHomePage(), routes: { "/page1": (context) => PageA(), "/page2": (context) => PageB(), }, );
接收參數:var args = ModalRoute.of(context).settings.arguments;
頁面返回
Navigator.pop(context);
接收頁面的返回值:
Navigator.push<void>( context, MaterialPageRoute( builder: (BuildContext context) => const MyHomePage(), ), ).then((dynamic result) { // 頁面返回result });
必須同時配合Navigator.pop<dynamic>(context, result);
還有路由刪除removeRoute
,路由替換replace
等。
2.fluro
直接使用Navigator
的主要問題是不易維護。如果某個頁面的傳參發生了變化,那么所有跳轉處都需要做修改。
所以我們可以使用現有封裝好的路由框架來替我們解決這些問題。比如fluro。
1.配置
添加依賴至pubspec.yaml
:
dependencies: fluro: ^2.0.3
定義唯一一個FluroRouter
對象:
static final FluroRouter router = FluroRouter();
剩下的就是添加路由處理器Handler
,下面代碼舉例添加了兩個頁面:
class Routes { static String home = '/home'; static String webViewPage = '/webView'; static final List<IRouterProvider> _listRouter = []; static final FluroRouter router = FluroRouter(); static void initRoutes() { /// 指定路由跳轉錯誤返回頁 router.notFoundHandler = Handler( handlerFunc: (BuildContext? context, Map<String, List<String>> params) { debugPrint('未找到目標頁'); return const NotFoundPage(); }); router.define(home, handler: Handler( handlerFunc: (BuildContext? context, Map<String, List<String>> params) => const Home())); // Routes.router.navigateTo(context, '${Routes.webViewPage}?title=標題&url=地址'); router.define(webViewPage, handler: Handler(handlerFunc: (_, params) { /// 接收參數 final String title = params['title']?.first ?? ''; final String url = params['url']?.first ?? ''; return WebViewPage(title: title, url: url); })); } }
配置fluro:
MaterialApp( onGenerateRoute: Routes.router.generator, );
初始化:
class MyApp extends StatelessWidget { MyApp() { Routes.initRoutes(); } ... }
2.使用方法
核心就一個方法navigateTo
,源碼如下:
Future navigateTo(BuildContext context, String path, {bool replace = false, bool clearStack = false, bool maintainState = true, bool rootNavigator = false, TransitionType? transition, Duration? transitionDuration, RouteTransitionsBuilder? transitionBuilder, RouteSettings? routeSettings}) { RouteMatch routeMatch = matchRoute(context, path, transitionType: transition, transitionsBuilder: transitionBuilder, transitionDuration: transitionDuration, maintainState: maintainState, routeSettings: routeSettings); Route<dynamic>? route = routeMatch.route; Completer completer = Completer(); Future future = completer.future; if (routeMatch.matchType == RouteMatchType.nonVisual) { completer.complete("Non visual route type."); } else { ///找不到時走`notFoundHandler` if (route == null && notFoundHandler != null) { route = _notFoundRoute(context, path, maintainState: maintainState); } if (route != null) { final navigator = Navigator.of(context, rootNavigator: rootNavigator); if (clearStack) { future = navigator.pushAndRemoveUntil(route, (check) => false); } else { future = replace ? navigator.pushReplacement(route) : navigator.push(route); } completer.complete(); } else { final error = "No registered route was found to handle '$path'."; print(error); completer.completeError(RouteNotFoundException(error, path)); } } return future; }
-
path
:路由名稱。 -
replace
:等同于pushReplacement
。 -
clearStack
:等同于pushAndRemoveUntil
。 -
transition
:頁面跳轉動畫,默認native,平臺默認動畫。 -
transitionDuration
:動畫時長。 -
transitionBuilder
:自定義動畫。 -
routeSettings
:用于傳遞數據。可使用context.settings.arguments
獲取。
具體的使用見項目routers目錄。
3.路由攔截
路由攔截可以實現權限控制。比如用戶沒有登錄,當進入某些需要登錄后才能顯示的頁面時,可以攔截跳轉進行判斷,引導用戶進入登錄頁。
MaterialApp有 onGenerateRoute
方法可以在跳轉時進行路由攔截。但是使用的fluro將這一屬性占用了,所以我們可以繼承 FluroRouter
類,重寫navigateTo
方法實現。
class MyFluroRouter extends FluroRouter { List<String> _loginList; set loginList(value) => _loginList = value; @override Future navigateTo( BuildContext context, String path, { bool replace = false, bool clearStack = false, bool maintainState = true, bool rootNavigator = false, TransitionType transition, Duration transitionDuration, transitionBuilder, RouteSettings routeSettings, }) { String pathToNavigate = path; AppRouteMatch routeMatched = this.match(path); String routePathMatched = routeMatched?.route?.route; if (routePathMatched != null) { //如果頁面需要登錄,修改路由路徑到登錄頁面 if (_loginList != null && !_loginList.contains(routePathMatched)) { pathToNavigate = '/login‘; } } return super.navigateTo(context, pathToNavigate, replace: replace, clearStack: clearStack, maintainState: maintainState, rootNavigator: rootNavigator, transition: transition, transitionDuration: transitionDuration, transitionBuilder: transitionBuilder, routeSettings: routeSettings); } }
3.封裝
fluro工具類:
class NavigatorUtils { static void push(BuildContext context, String path, {bool replace = false, bool clearStack = false, Object? arguments}) { unfocus(); Routes.router.navigateTo(context, path, replace: replace, clearStack: clearStack, transition: TransitionType.native, routeSettings: RouteSettings( arguments: arguments, ), ); } static void pushResult(BuildContext context, String path, Function(Object) function, {bool replace = false, bool clearStack = false, Object? arguments}) { unfocus(); Routes.router.navigateTo(context, path, replace: replace, clearStack: clearStack, transition: TransitionType.native, routeSettings: RouteSettings( arguments: arguments, ), ).then((Object? result) { // 頁面返回result為null if (result == null) { return; } function(result); }).catchError((dynamic error) { debugPrint('$error'); }); } /// 返回 static void goBack(BuildContext context) { unfocus(); Navigator.pop(context); } /// 帶參數返回 static void goBackWithParams(BuildContext context, Object result) { unfocus(); Navigator.pop<Object>(context, result); } static void unfocus() { FocusManager.instance.primaryFocus?.unfocus(); } }
模塊管理:
import 'package:fluro/fluro.dart'; abstract class IRouterProvider { void initRouter(FluroRouter router); }
實現接口:
class LoginRouter implements IRouterProvider{ static String loginPage = '/login'; static String registerPage = '/login/register'; @override void initRouter(FluroRouter router) { router.define(loginPage, handler: Handler(handlerFunc: (_, __) => const LoginPage())); router.define(registerPage, handler: Handler(handlerFunc: (_, __) => const RegisterPage())); } }
各模塊初始化,放在Routes的initRoutes中:
/// 各自路由由各自模塊管理,統一在此添加初始化 _listRouter.add(LoginRouter()); ... /// 初始化路由 void initRouter(IRouterProvider routerProvider) { routerProvider.initRouter(router); } _listRouter.forEach(initRouter);
目前Flutter團隊有維護一款路由框架go_router
(支持Navigator 2.0),但目前有部分功能缺失,比如不支持接收頁面的返回值,沒有pushAndRemoveUntil
方法。
期待后面功能的完善。但就目前來說,對于Android 和iOS平臺開發來說fluro的功能足夠使用了。
原文鏈接:https://blog.csdn.net/qq_17766199/article/details/127474553
相關推薦
- 2023-05-11 SQL?多表聯合查詢的幾種方式詳解_MsSql
- 2024-03-22 【IDEA】解決配置xml文件時,idea提示 application context not co
- 2022-08-13 Docker(Windows版)安裝zookeeper+kafka
- 2022-12-31 C++模擬Linux?Shell編寫一個自定義命令_C 語言
- 2023-07-09 echart 設置柱狀圖y軸最大刻度
- 2021-12-02 Golang共享變量如何解決問題_Golang
- 2022-07-03 python類的私有屬性和公共屬性說明_python
- 2022-06-06 python?利用?PrettyTable?美化表格_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支