Flutter路由管理插件riverpod_navigator_core的使用
Flutter路由管理插件 riverpod_navigator_core
的使用
简介
riverpod_navigator_core
是一个基于 Riverpod 和 Navigator 2.0 的强大且简单的 Flutter 路由管理插件。它解决了以下问题:
- 严格的类型导航:你可以使用
navigate([HomeSegment(), BookSegment(id: 2)])
而不是navigate('home/book;id:2')
。 - 异步导航:当更改导航状态需要执行异步操作时(如从网络加载或保存数据)。
- 多个 Provider:当导航状态依赖于多个 Riverpod Provider 时。
- 简化编码:将导航问题简化为类集合的操作。
- 更好的关注点分离:通过 Riverpod 实现 UI 和模型的分离,可以在不编写任何 Flutter 小部件的情况下开发和测试导航逻辑。
- 嵌套导航:只需使用嵌套的 Riverpod
ProviderScope()
和 Flutter 的Router
小部件。
示例 Demo
步骤 1 - 定义 TypedSegment 类
首先,定义用于表示不同类型路径段的类:
class HomeSegment extends TypedSegment {
const HomeSegment();
factory HomeSegment.decode(UrlPars pars) => const HomeSegment();
}
class BookSegment extends TypedSegment {
const BookSegment({required this.id});
factory BookSegment.decode(UrlPars pars) => BookSegment(id: pars.getInt('id'));
final int id;
@override
void encode(UrlPars pars) => pars.setInt('id', id);
}
步骤 2 - 配置 AppNavigator
通过扩展 RNavigator
类来配置 AppNavigator
:
class AppNavigator extends RNavigator {
AppNavigator(Ref ref)
: super(
ref,
[
RRoute<HomeSegment>(
'home',
HomeSegment.decode,
HomeScreen.new,
),
RRoute<BookSegment>(
'book',
BookSegment.decode,
BookScreen.new,
),
],
);
}
步骤 3 - 在 MaterialApp.router
中使用 AppNavigator
如果你熟悉 Flutter Navigator 2.0 和 Riverpod,以下代码应该很容易理解:
class App extends ConsumerWidget {
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final navigator = ref.read(navigatorProvider) as AppNavigator;
return MaterialApp.router(
title: 'Riverpod Navigator Example',
routerDelegate: navigator.routerDelegate,
routeInformationParser: navigator.routeInformationParser,
);
}
}
步骤 4 - 配置 Riverpod ProviderScope
在主入口点中配置 Riverpod ProviderScope
:
void main() => runApp(
ProviderScope(
overrides: riverpodNavigatorOverrides([HomeSegment()], AppNavigator.new),
child: const App(),
),
);
步骤 5 - 编写屏幕小部件
编写两个屏幕小部件 HomeScreen
和 BookScreen
,并继承自 RScreen
小部件:
class BookScreen extends RScreen<AppNavigator, BookSegment> {
const BookScreen(BookSegment segment) : super(segment);
@override
Widget buildScreen(ref, navigator, appBarLeading) => Scaffold(
appBar: AppBar(
title: Text('Book ${segment.id}'),
leading: appBarLeading,
),
body: Center(
child: ElevatedButton(
onPressed: () => navigator.push(BookSegment(id: segment.id + 1)),
child: Text('Next Book'),
),
),
);
}
运行示例、源码和测试代码
异步导航
定义 TypedSegment 类
为每个 TypedSegment
应用 AsyncSegment
混入:
class HomeSegment extends TypedSegment with AsyncSegment<String>{
....
}
class BookSegment extends TypedSegment with AsyncSegment<String>{
....
}
配置 AppNavigator
在 RRoute
定义中添加 opening
, closing
或 replacing
动作:
class AppNavigator extends RNavigator {
AppNavigator(Ref ref)
: super(
ref,
[
RRoute<HomeSegment>(
'home',
HomeSegment.decode,
HomeScreen.new,
opening: (sNew) => sNew.setAsyncValue(_simulateAsyncResult('Home.opening', 2000)),
),
RRoute<BookSegment>(
'book',
BookSegment.decode,
BookScreen.new,
opening: (sNew) => sNew.setAsyncValue(_simulateAsyncResult('Book ${sNew.id}.opening', 240)),
replacing: (sOld, sNew) => sNew.setAsyncValue(_simulateAsyncResult('Book ${sOld.id}=>${sNew.id}.replacing', 800)),
closing: (sOld) => Future.delayed(Duration(milliseconds: 500)),
),
],
);
}
Future<String> _simulateAsyncResult(String asyncResult, int msec) async {
await Future.delayed(Duration(milliseconds: msec));
return '$asyncResult: async result after $msec msec';
}
使用异步动作结果构建屏幕
在构建屏幕时使用异步动作的结果:
...
Text('Async result: "${segment.asyncValue}"'),
...
其他功能和示例
示例安装
克隆 riverpod_navigator 仓库 后,进入 examples/doc
子目录并执行以下命令:
flutter create .
flutter pub get
更多关于Flutter路由管理插件riverpod_navigator_core的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter路由管理插件riverpod_navigator_core的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 riverpod_navigator_core
插件进行 Flutter 路由管理的代码示例。riverpod_navigator_core
是一个与 Riverpod 状态管理库结合使用的 Flutter 路由管理插件。它允许你以声明式的方式管理应用中的路由。
首先,确保你已经在 pubspec.yaml
文件中添加了必要的依赖:
dependencies:
flutter:
sdk: flutter
flutter_riverpod: ^1.0.0
riverpod_navigator_core: ^1.0.0
然后,运行 flutter pub get
来安装这些依赖。
接下来,我们来看一个完整的示例,展示如何使用 riverpod_navigator_core
。
主应用入口 (main.dart)
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_navigator_core/riverpod_navigator_core.dart';
import 'routes.dart'; // 我们稍后会创建这个文件
void main() {
runApp(
ProviderScope(
child: MaterialApp.router(
routeInformationParser: RiverpodRouteInformationParser<RiverpodRouteData>(),
routerDelegate: RiverpodRouterDelegate<RiverpodRouteData>(
navigatorKey: GlobalKey(),
routesBuilder: (context, state) => Routes().buildRoutes(),
),
),
),
);
}
路由配置 (routes.dart)
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_navigator_core/riverpod_navigator_core.dart';
import 'screens/home_screen.dart';
import 'screens/details_screen.dart';
class Routes {
Router buildRoutes() {
return Router(
routes: [
RiverpodRoute(
path: '/',
builder: (_, __) => const HomeScreen(),
),
RiverpodRoute(
path: '/details/:id',
builder: (_, routeData) {
final id = routeData.parameters['id']!;
return DetailsScreen(id: id);
},
),
],
);
}
}
主屏幕 (screens/home_screen.dart)
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_navigator_core/riverpod_navigator_core.dart';
class HomeScreen extends ConsumerWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Screen'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// 导航到详情页面,传递一个示例ID
context.read(navigationRef).pushNamed('/details/123');
},
child: const Text('Go to Details'),
),
),
);
}
}
详情屏幕 (screens/details_screen.dart)
import 'package:flutter/material.dart';
class DetailsScreen extends StatelessWidget {
final String id;
const DetailsScreen({Key? key, required this.id}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Details Screen'),
),
body: Center(
child: Text('Details for ID: $id'),
),
);
}
}
注意事项
- 依赖注入:
riverpod_navigator_core
依赖于 Riverpod,因此你需要使用ProviderScope
来包裹你的应用。 - 路由参数:在
RiverpodRoute
中,你可以使用routeData.parameters
来访问 URL 中的参数。 - 导航:使用
context.read(navigationRef).pushNamed
或pop
方法来进行导航操作。
这个示例展示了如何使用 riverpod_navigator_core
来配置和管理 Flutter 应用中的路由。通过这种方式,你可以将路由配置与状态管理紧密结合,从而构建一个更加模块化和可维护的应用。