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ù)。可使用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 Room數(shù)據(jù)庫自動升級與遷移的策略
在 Android 應(yīng)用開發(fā)中,Room 是 Google 提供的一個輕量級數(shù)據(jù)庫框架,用于簡化與 SQLite 的交互,本文將介紹 Room 數(shù)據(jù)庫升級的幾種場景和常見的處理方法,包括手動遷移和自動遷移的策略,需要的朋友可以參考下2024-09-09
Android開發(fā)實現(xiàn)根據(jù)字母快速定位側(cè)邊欄
這篇文章主要為大家詳細介紹了Android開發(fā)實現(xiàn)根據(jù)字母快速定位側(cè)邊欄,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
Android Activity的跳轉(zhuǎn)與傳值詳解
這篇文章主要介紹了Android Activity的跳轉(zhuǎn)與傳值詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06
Android 如何使用SQLite保存數(shù)據(jù)
對于重復(fù)數(shù)據(jù)或結(jié)構(gòu)化數(shù)據(jù)(例如聯(lián)系信息),將數(shù)據(jù)保存到數(shù)據(jù)庫是理想選擇,SQL 數(shù)據(jù)庫的主要原則之一是架構(gòu),即數(shù)據(jù)庫組織方式的正式聲明,本篇文章介紹在 Android 上使用 SQLite 數(shù)據(jù)庫,感興趣的朋友一起看看吧2024-03-03
Android使用AsyncTask下載圖片并顯示進度條功能
這篇文章主要介紹了Android使用AsyncTask下載圖片并顯示進度條功能,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-02-02

