Flutter路由框架Fluro使用教程詳細講解
1.Navigator使用簡介
使用Flutter 的Navigator
導(dǎo)航器可以實現(xiàn)頁面的跳轉(zhuǎn),Navigator
的使用方法簡單介紹一下:
頁面跳轉(zhuǎn):
Navigator.push<void>( context, MaterialPageRoute( builder: (BuildContext context) => const MyHomePage(), ), );
頁面跳轉(zhuǎn)的同時關(guān)閉當(dāng)前頁面(頁面替換):
Navigator.pushReplacement<void, void>( context, MaterialPageRoute( builder: (BuildContext context) => const MyHomePage(), ), );
頁面跳轉(zhuǎn)的同時關(guān)閉到之前的某一個頁面:
Navigator.pushAndRemoveUntil<void>( context, MaterialPageRoute( builder: (BuildContext context) => const MyHomePage(), ), (route) => false // ModalRoute.withName('/') );
也可以直接使用路由名稱進行上面操作,例如跳轉(zhuǎn):Navigator.pushNamed(context, '/home');
路由名稱需要提前在MaterialApp
中定義好。
MaterialApp( title: 'Flutter Demo', home: MyHomePage(), routes: { "/page1": (context) => PageA(), "/page2": (context) => PageB(), }, );
接收參數(shù):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
的主要問題是不易維護。如果某個頁面的傳參發(fā)生了變化,那么所有跳轉(zhuǎn)處都需要做修改。
所以我們可以使用現(xiàn)有封裝好的路由框架來替我們解決這些問題。比如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() { /// 指定路由跳轉(zhuǎn)錯誤返回頁 router.notFoundHandler = Handler( handlerFunc: (BuildContext? context, Map<String, List<String>> params) { debugPrint('未找到目標(biāo)頁'); 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=標(biāo)題&url=地址'); router.define(webViewPage, handler: Handler(handlerFunc: (_, params) { /// 接收參數(shù) 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
:頁面跳轉(zhuǎn)動畫,默認native,平臺默認動畫。transitionDuration
:動畫時長。transitionBuilder
:自定義動畫。routeSettings
:用于傳遞數(shù)據(jù)??墒褂?code>context.settings.arguments獲取。
具體的使用見項目routers目錄。
3.路由攔截
路由攔截可以實現(xiàn)權(quán)限控制。比如用戶沒有登錄,當(dāng)進入某些需要登錄后才能顯示的頁面時,可以攔截跳轉(zhuǎn)進行判斷,引導(dǎo)用戶進入登錄頁。
MaterialApp有 onGenerateRoute
方法可以在跳轉(zhuǎn)時進行路由攔截。但是使用的fluro將這一屬性占用了,所以我們可以繼承 FluroRouter
類,重寫navigateTo
方法實現(xiàn)。
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); } /// 帶參數(shù)返回 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); }
實現(xiàn)接口:
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中:
/// 各自路由由各自模塊管理,統(tǒng)一在此添加初始化 _listRouter.add(LoginRouter()); ... /// 初始化路由 void initRouter(IRouterProvider routerProvider) { routerProvider.initRouter(router); } _listRouter.forEach(initRouter);
目前Flutter團隊有維護一款路由框架go_router
(支持Navigator 2.0),但目前有部分功能缺失,比如不支持接收頁面的返回值,沒有pushAndRemoveUntil
方法。
期待后面功能的完善。但就目前來說,對于Android 和iOS平臺開發(fā)來說fluro的功能足夠使用了。
到此這篇關(guān)于Flutter路由框架Fluro使用教程詳細講解的文章就介紹到這了,更多相關(guān)Flutter Fluro內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android SwipeRefreshLayout下拉刷新源碼解析
這篇文章主要為大家詳細解析了Android SwipeRefreshLayout下拉刷新源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-11-11Android 控件(button)對齊方法實現(xiàn)詳解
horizontal是讓所有的子元素按水平方向從左到右排列,vertical是讓所有的子元素按豎直方向從上到下排列,下面為大家介紹下控件(button)的對齊方法2013-06-06Android build.gradle版本名打包配置的方法
這篇文章主要介紹了Android build.gradle版本名打包配置的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-02-02Android底部導(dǎo)航欄的三種風(fēng)格實現(xiàn)
這篇文章主要介紹了Android底部導(dǎo)航欄的三種風(fēng)格實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06Android應(yīng)用開發(fā)中CardView的初步使用指南
這篇文章主要介紹了Android應(yīng)用開發(fā)中CardView的初步使用指南,CardView主要處理一些卡片型的視圖布局,需要的朋友可以參考下2016-02-02Kotlin協(xié)程之Flow觸發(fā)與消費示例解析
Kotlin協(xié)程中,當(dāng)需要消費流時,會調(diào)用collect方法,觸發(fā)流的消費,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-09-09基于android中的各種顏色在drawable.xml中的值詳解
本篇文章是對在android中的各種顏色在drawable.xml中的值進行了詳細的介紹。需要的朋友參考下2013-05-05