# Flutter App頁面路由以及路由攔截的示例分析
## 一、前言
在移動應用開發中,頁面導航和路由管理是核心功能之一。Flutter作為跨平臺開發框架,提供了靈活的路由機制。本文將深入探討:
1. Flutter路由系統的基礎實現
2. 命名路由的進階用法
3. 動態路由參數傳遞技巧
4. 路由攔截的典型應用場景
5. 綜合實戰案例演示
## 二、Flutter路由基礎實現
### 2.1 基本路由跳轉
Flutter中最基礎的路由跳轉使用`Navigator.push`:
```dart
// 跳轉到新頁面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailPage()),
);
// 返回上一頁
Navigator.pop(context);
MaterialPageRoute是Material Design風格的路由組件:
MaterialPageRoute(
builder: (context) => TargetPage(), // 頁面構建器
settings: RouteSettings( // 路由配置
name: '/detail', // 路由名稱
arguments: {'id': 123}, // 傳遞參數
),
maintainState: true, // 是否保持狀態
fullscreenDialog: false, // 是否全屏對話框樣式
)
對于iOS風格應用,可使用CupertinoPageRoute:
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => IosStylePage(),
title: "詳情頁",
),
);
在MaterialApp中配置路由表:
MaterialApp(
routes: {
'/': (context) => HomePage(),
'/detail': (context) => DetailPage(),
'/profile': (context) => ProfilePage(),
},
)
// 普通跳轉
Navigator.pushNamed(context, '/detail');
// 替換當前路由
Navigator.pushReplacementNamed(context, '/profile');
// 跳轉并移除之前所有路由
Navigator.pushNamedAndRemoveUntil(
context,
'/login',
(route) => false,
);
// 發送參數
Navigator.pushNamed(
context,
'/detail',
arguments: {'id': 1001, 'title': '商品詳情'},
);
// 接收參數
final args = ModalRoute.of(context)!.settings.arguments as Map;
// 定義帶參數的路由
routes: {
'/user/:uid': (context) => UserPage(),
}
// 跳轉時
Navigator.pushNamed(context, '/user/10086');
MaterialApp(
onGenerateRoute: (settings) {
// 處理動態路由
if (settings.name!.startsWith('/product/')) {
final productId = settings.name!.split('/')[2];
return MaterialPageRoute(
builder: (context) => ProductPage(id: productId),
);
}
return null; // 其他路由按默認方式處理
},
)
onGenerateRoute: (settings) {
// 權限檢查示例
if (_needAuth(settings.name) && !_isLoggedIn) {
return MaterialPageRoute(
builder: (context) => LoginPage(),
);
}
// 其他路由處理...
}
class AuthInterceptor {
static Route? interceptor(RouteSettings settings) {
final authRoutes = ['/profile', '/settings'];
if (authRoutes.contains(settings.name)) {
if (!UserStore.isLogin) {
return MaterialPageRoute(
builder: (_) => LoginPage(
returnRoute: settings.name,
),
);
}
}
return null;
}
}
// 在MaterialApp中使用
onGenerateRoute: (settings) {
return AuthInterceptor.interceptor(settings) ??
_defaultRoute(settings);
}
Route createCustomRoute(Widget page) {
return PageRouteBuilder(
pageBuilder: (_, __, ___) => page,
transitionsBuilder: (_, animation, __, child) {
return FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: Tween<double>(begin: 0.9, end: 1.0).animate(
CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
),
),
child: child,
),
);
},
);
}
MaterialApp(
onGenerateRoute: (settings) {
// 攔截未登錄訪問
if (_needLogin(settings.name) && !_isLogin) {
return MaterialPageRoute(
builder: (_) => LoginPage(),
);
}
// 動態路由處理
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (_) => HomePage());
case '/product/:id':
final id = settings.name!.split('/')[2];
return ProductPageRoute(productId: id);
case '/search':
return SlideRightRoute(page: SearchPage());
default:
return MaterialPageRoute(
builder: (_) => NotFoundPage(),
);
}
},
)
class RouteObserver extends NavigatorObserver {
@override
void didPush(Route route, Route? previousRoute) {
debugPrint('進入頁面: ${route.settings.name}');
Analytics.trackPageView(route.settings.name);
}
@override
void didPop(Route route, Route? previousRoute) {
debugPrint('離開頁面: ${route.settings.name}');
}
}
// 注冊觀察者
MaterialApp(
navigatorObservers: [RouteObserver()],
)
路由懶加載:
routes: {
'/heavy': (context) => FutureBuilder(
future: HeavyPage.loadLibrary(),
builder: (_, snapshot) => snapshot.hasData ? HeavyPage() : LoadingPage(),
),
}
避免重復構建:
// 使用GlobalKey保持頁面狀態
final homeKey = GlobalKey();
routes: {
'/': (context) => HomePage(key: homeKey),
}
路由表分模塊管理: “`dart // 分模塊定義路由 final authRoutes = { ‘/login’: (context) => LoginPage(), ‘/register’: (context) => RegisterPage(), };
final mainRoutes = { ‘/home’: (context) => HomePage(), ‘/profile’: (context) => ProfilePage(), };
// 合并路由表 routes: { …authRoutes, …mainRoutes, }
## 八、常見問題解決方案
### 8.1 路由堆棧管理
```dart
// 清空路由棧跳轉到首頁
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => HomePage()),
(route) => false,
);
// 返回到指定路由
Navigator.popUntil(context, ModalRoute.withName('/dashboard'));
// 定義路由參數類
class DetailParams {
final String id;
final String? category;
DetailParams({required this.id, this.category});
static DetailParams? fromObject(dynamic data) {
if (data is Map) {
return DetailParams(
id: data['id']?.toString() ?? '',
category: data['category']?.toString(),
);
}
return null;
}
}
// 使用參數
final params = DetailParams.fromObject(
ModalRoute.of(context)!.settings.arguments
);
Flutter路由系統的主要技術要點:
隨著Flutter 3.x版本的更新,路由系統還在持續演進。建議開發者關注:
”`
(注:實際字數約4200字,可根據需要調整各部分內容的詳細程度)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。