flutter - 在命名路由器中传递参数的最佳方法
问题描述
我有两个命名的路由器小部件,我应该如何使用 bloc 模式将参数从一个传递到另一个?
// main.dart
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<OneBloc>(create: (BuildContext context) => OneBloc()),
BlocProvider<TwoBloc>(
create: (BuildContext context) => TwoBloc())
],
child: MaterialApp(
title: 'testApp',
initialRoute: '/one',
routes: {
'/one': (context) => One(),
'/two': (context) => Two()
},
),
);
}
}
// one_bloc.dart
class OneBloc extends Bloc<OneEvent, OneState> {
OneBloc() : super(OneInitial());
@override
Stream<OneState> mapEventToState(
OneEvent event,
) async* {
if (event is PassParameter) {
yield NavigateToTwo('parameter from One');
}
}
}
// one_state.dart
@immutable
abstract class OneState extends Equatable {
const OneState();
@override
List<Object> get props => [];
}
class NavigateToTwo extends OneState {
final String parameter;
NavigateToTwo(this.parameter);
}
// One.dart -- part of UI code
@override
Widget build(BuildContext context) {
return BlocConsumer<OneBloc, OneState>(listener: (context, state) {
if (state is NavigateToTwo) {
Navigator.pushNamed(context, '/two'); // how to pass the state.parameter to TwoBloc
}
},
// other code.
更新
在查看官网的 todo 示例后,它应该使用 TwoBloc 中的 StreamSubscription 来监听 OneBloc NavigateToTwo 状态以获取参数。
解决方案
首先,您创建了一个类变量来接收要在类之间传递的参数。
Class One {
final a;
One({this.a});
...
}
您可以通过导航器将参数作为这样的参数传递
Map<String, dynamic> myArguments = {"argumentKey": value};
Navigator.pushNamed(context, '/two', arguments: myArgument);
然后你可以像这样在 MaterialApp 的 onGenerateRoute() 中访问这个参数
MaterialApp(
onGenerateRoute: (settings) {
final args = settings.arguments;
if (settings.name == '/one') {
final argumentForPageOne = args["argumentForPageOne"];
}
if (settings.name == '/two') {
final argumentForPageTwo = args["argumentForPageTwo"];
}
Map<String, Widget> widgets = {
'/one': One(a: argumentForPageOne),
'/two': Two(b: argumentForPageTwo)
}
return MaterialPageRoute(
builder: (context) {
return widgets[settings.name];
},
);
}
},
);
对于具有多个屏幕的大型项目,您必须创建自定义路由器类以进行导航。
例子:
class RouterService {
final GlobalKey<NavigatorState> navigationKey = GlobalKey<NavigatorState>();
Route<dynamic> generateRoutes(RouteSettings settings) {
final List<String> validRoutes = [
'/home',
'/introduction',
];
PageRouteBuilder<dynamic> customRoutes(
String route, Map<String, dynamic> args) {
String message;
bool showTutorial;
if (args != null) {
if (args.containsKey('message')) {
message = args['message'];
}
if (args.containsKey('showTutorial')) {
showTutorial = args['showTutorial'];
}
}
Map<String, Widget> screens = {
'/home': HomeScreen(
message: message,
showTutorial: showTutorial,
),
'/introduction': IntroductionScreen(),
...
};
return PageRouteBuilder(
pageBuilder: (_, __, ___) => screens[route],
transitionsBuilder: (_, anim, __, child) => FadeTransition(
opacity: anim,
child: child,
),
transitionDuration: Duration(milliseconds: 250));
}
}
if (validRoutes.contains(settings.name)) {
return customRoutes(settings.name, settings.arguments);
} else {
return MaterialPageRoute(builder: (_) {
return NotFoundScreen();
});
}
}
然后在 MaterialApp 中使用这个自定义路由器
MaterialApp(
...,
onGenerateRoute: RouterService().generateRoutes,
)
推荐阅读
- c++ - 如何在没有 reinterpret_cast 的情况下使用 dlsym() 加载函数?
- google-cloud-platform - GCP 上的 Terraform 共享 VPC - 静态内部 IP 地址
- vb.net - 如果条件完成,如何做出超过 2 的语句?
- python - 如何将 Bokeh 中的滑块值传递回 Python 代码
- python - 带有 Tensorflow 扩展管道的 TF-Lite-Converter(芝加哥出租车管道示例)
- reactjs - 对标准化数据进行排序的最佳方法是什么?
- macos - macOS:通过在键盘上键入从列表中选择项目
- python - 如何获得两个熊猫系列文本列的交集?
- java - JPQL CONCAT 函数是布尔值而不是字符串
- linux - 堆栈保护器已启用,但编译器支持已损坏