【问题标题】:Best way to pass parameter in named router在命名路由器中传递参数的最佳方法
【发布时间】:2020-12-21 12:46:47
【问题描述】:

我有两个命名的路由器小部件,我应该如何使用 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.

更新

查看official web site中的todo示例后,应该使用TwoBloc中的StreamSubscription监听OneBloc NavigateToTwo状态获取参数。

【问题讨论】:

    标签: flutter flutter-bloc


    【解决方案1】:

    首先你已经创建了一个类变量来接收你想在类之间传递的参数。

    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,
    )
    

    【讨论】:

      【解决方案2】:

      首先在您的 MaterialApp 上 添加这个

      onGenerateRoute: (settings){
          ///write your code here
      }
      

      当您的小部件树发生更改时,MaterialApp 将运行 onGenerateRoute。然后它具有(设置)属性,您可以使用这些属性来获取参数

      settings.arguments
      

      如果你想知道地狱的论点来自哪里。让我带你回到导航器。

      Usually, you can use it to pass the data on the arguments key, like this 
      Navigator.pushNamed(context, "your routeName", arguments:"your object here");
      

      让我们回到 onGenerateRoute 这是 onGenerateRoute 用法的完整示例

      onGenerateRoute: (settings){
      MaterialPageRoute routes;
      switch (settings.name) {
          case OrderDetail.routeName:
            dynamic args = settings.arguments;
            routes = MaterialPageRoute(
              builder: (context) {
                return OrderDetail(args);
              },
            );
            break;
          case ShowLocation.routeName:
            dynamic args = settings.arguments;
            routes = MaterialPageRoute(
              builder: (context) {
                return ShowLocation(args);
              },
            );
            break;
          case AddressDetail.routeName:
            dynamic args = settings.arguments;
            routes = MaterialPageRoute(
              builder: (context) {
                return AddressDetail(args);
              },
            );
            break;
        }
        return routes;
      }
      

      结论:

      onGenerateRoute: (settings){
          settings.name;/// This will return a routeName which you called on the navigator pushNamed
          settings.arguments;/// This will return an object which you invoked on the navigator pushNamed it can be anything (dynamic) but also it can be specific, depends on what you set on the onGenerate Route !!
          ///Navigator.pushNamed(context, routeName, arguments:"your args");
      }
      

      祝你好运

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-08
        • 2020-07-24
        • 2021-06-30
        • 2011-06-01
        • 2022-01-11
        • 1970-01-01
        • 2020-06-13
        • 1970-01-01
        相关资源
        最近更新 更多