Flutter路由与状态管理插件riverpod_consumer_router_delegate的使用
Flutter路由与状态管理插件riverpod_consumer_router_delegate的使用
riverpod_consumer_router_delegate
特性
这个包让你能够将 flutter_riverpod 包与 flutter navigator 2.0 API 结合起来使用。
在自定义的路由器委托类中,你可以像在小部件中一样使用 <code>ref.watch()</code>
、<code>ref.read()</code>
、<code>ref.listen()</code>
和 <code>ref.refresh()</code>
方法。
使用方法
以下是使用 riverpod_consumer_router_delegate
的完整步骤和代码示例:
1. 扩展你的 RouterDelegate
类为 ConsumerRouterDelegate
class MyRouterDelegate extends ConsumerRouterDelegate<MyRouteConfig>
with PopNavigatorRouterDelegateMixin<MyRouteConfig>, ChangeNotifier {
// 确保将 `ref` 传递给 `super` 构造函数
MyRouterDelegate(Ref ref) : super(ref);
// ...
}
2. 实现 <code>onDependenciesUpdate()</code>
方法
如果你的路由器委托是一个 <code>ChangeNotifier</code>
,那么可以调用 <code>notifyListeners()</code>
方法:
[@override](/user/override)
void onDependenciesUpdate() {
notifyListeners();
}
3. 在自定义路由器委托类中,不要覆盖 <code>build</code>
方法,而是编写一个 <code>builder</code>
方法
Widget builder(BuildContext context) {
// 在这里编写你的路由构建逻辑
}
注意:<code>ref</code>
不是你传递给 <code>super</code>
构造函数的那个 ref
。
4. 添加一个 <code>ChangeNotifierProvider</code>
来管理你的路由器委托实例
final routerDelegateProvider = ChangeNotifierProvider((ref) => MyRouterDelegate(ref));
5. 在 <code>MaterialApp</code>
周围包裹一个 <code>ProviderScope</code>
,并将路由器委托实例传递给 <code>MaterialApp.router</code>
的构造函数
void main() {
runApp(
const ProviderScope(child: MyApp()),
);
}
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp.router(
routerDelegate: ref.watch(routerDelegateProvider), // 使用 provider 提供的路由器委托
routeInformationParser: ColorRouteInformationParser(), // 路由信息解析器
);
}
}
动机
Flutter 的导航器 2.0 API 采用了声明式的方法,但直接与 <code>riverpod</code>
配合使用存在一些问题。
正如在 此问题 中讨论的那样,在路由器委托的 <code>build</code>
方法中直接使用 <code>riverpod</code>
的方法(例如 <code>ref.watch()</code>
)会导致一些问题。
社区建议在路由器委托的构造函数中添加所有依赖提供者的监听器,但这不是一个好主意,因为它既丑陋又容易出错。
因此,我创建了这个包。只需扩展你的路由器委托类,并将 <code>ref</code>
传递给父类构造函数,然后编写一个 <code>builder</code>
方法而不是 <code>build</code>
方法即可。它会在幕后完成魔法,让你可以像在小部件中一样使用 <code>ref.*</code>
方法,无需任何担忧。
其他信息
欢迎提交问题和拉取请求。
完整示例代码
以下是从示例文件中提取的完整代码:
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'router/route_information_parser.dart';
import 'service_locator.dart';
void main() {
runApp(
const ProviderScope(child: MyApp()),
);
}
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp.router(
routeInformationParser: ColorRouteInformationParser(),
routerDelegate: ref.watch(routerDelegateProvider),
);
}
}
更多关于Flutter路由与状态管理插件riverpod_consumer_router_delegate的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,路由管理和状态管理是两个非常重要的概念。riverpod_consumer_router_delegate
是一个结合了 Riverpod
状态管理和 Router
路由管理的插件,它允许你在使用 Riverpod
进行状态管理的同时,通过 Router
来管理应用的路由。
1. 安装依赖
首先,你需要在 pubspec.yaml
文件中添加 riverpod
和 riverpod_consumer_router_delegate
的依赖:
dependencies:
flutter:
sdk: flutter
riverpod: ^2.0.0
riverpod_consumer_router_delegate: ^0.1.0
然后运行 flutter pub get
来安装依赖。
2. 基本使用
2.1 创建 RouterDelegate
RouterDelegate
是 Router
的核心部分,它负责处理路由的导航逻辑。riverpod_consumer_router_delegate
提供了一个 ConsumerRouterDelegate
,它允许你在路由管理中使用 Riverpod
的状态。
import 'package:flutter/material.dart';
import 'package:riverpod/riverpod.dart';
import 'package:riverpod_consumer_router_delegate/riverpod_consumer_router_delegate.dart';
final routerDelegateProvider = Provider<ConsumerRouterDelegate>((ref) {
return ConsumerRouterDelegate(
routeInformationParser: MyRouteInformationParser(),
builder: (context, route) {
switch (route) {
case '/':
return HomeScreen();
case '/details':
return DetailsScreen();
default:
return NotFoundScreen();
}
},
);
});
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp.router(
routeInformationParser: MyRouteInformationParser(),
routerDelegate: context.read(routerDelegateProvider),
);
}
}
2.2 创建 RouteInformationParser
RouteInformationParser
负责将 RouteInformation
转换为应用内部的路由状态。
class MyRouteInformationParser extends RouteInformationParser<String> {
[@override](/user/override)
Future<String> parseRouteInformation(RouteInformation routeInformation) async {
return routeInformation.location ?? '/';
}
[@override](/user/override)
RouteInformation restoreRouteInformation(String configuration) {
return RouteInformation(location: configuration);
}
}
2.3 使用 ConsumerRouterDelegate
进行导航
你可以在任何地方使用 ConsumerRouterDelegate
来进行导航。例如,在 HomeScreen
中导航到 DetailsScreen
:
class HomeScreen extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: ElevatedButton(
onPressed: () {
context.read(routerDelegateProvider).push('/details');
},
child: Text('Go to Details'),
),
),
);
}
}
2.4 处理路由参数
你可以通过 ConsumerRouterDelegate
传递路由参数:
context.read(routerDelegateProvider).push('/details', arguments: {'id': 123});
在 DetailsScreen
中获取参数:
class DetailsScreen extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
final arguments = ModalRoute.of(context)?.settings.arguments as Map<String, dynamic>?;
final id = arguments?['id'];
return Scaffold(
appBar: AppBar(title: Text('Details')),
body: Center(
child: Text('Details for item $id'),
),
);
}
}
3. 结合 Riverpod
进行状态管理
ConsumerRouterDelegate
允许你在路由管理中使用 Riverpod
的状态。例如,你可以在 ConsumerRouterDelegate
的 builder
中使用 Consumer
来获取状态:
final counterProvider = StateProvider<int>((ref) => 0);
class HomeScreen extends ConsumerWidget {
[@override](/user/override)
Widget build(BuildContext context, WidgetRef ref) {
final counter = ref.watch(counterProvider);
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Counter: $counter'),
ElevatedButton(
onPressed: () {
ref.read(counterProvider.notifier).state++;
},
child: Text('Increment'),
),
],
),
),
);
}
}