如何通过Navigator传递提供商?

时间:2019-08-21 19:22:56

标签: flutter dart flutter-provider

我需要从Model2homepage的传递提供者(Page2),因此当用户返回homepageonWillPop)时,我可以从提供者(Model2)并更新homepage

但是当我打电话给_onPaidBackPress(context)时出现错误:

  

未处理的异常:错误:找不到正确的   消费者微件上方的提供商

StatefulWidget在首页中:

@override
  Widget build(BuildContext context) {
return ChangeNotifierProxyProvider<Model1, Model2>(
initialBuilder: (_) => Model2(),
  builder: (_, model1, model2) => model2
    ..string = model1.string,
),
  child: Consumer<Model2>(
    builder: (context, model2, _) =>

...
                        await Navigator.push(
                            context,
                            new MaterialPageRoute(
                                builder: (BuildContext context) =>
                                    new Page2(
                                        context: context)));

在第2页中:

class Page2 extends StatefulWidget {

  final BuildContext context;

  Page2({Key key, this.context}) : super(key: key);

  @override
  State createState() => new Page2State(context: context);
}

class Page2State extends State<Page2> {

  final context;

  ChatScreenState({Key key, this.context});

@override
  Widget build(BuildContext context) {

    return Consumer<Model1>(
      builder: (context, model, _) {

        return new WillPopScope(
              onWillPop: () => model.isPaid ? _onPaidBackPress(context) : _onBackPressed(context),




Future<void> _onPaidBackPress(context) async {


final model2 = Provider.of<Model2>(context, listen: false);

  return showDialog<void>(
    context: context,
    barrierDismissible: false, 
    builder: (BuildContext context) {
      return 


    Provider.value(value: model2, child:


AlertDialog(
        title: Text('Back'),
        content: SingleChildScrollView(
          child: ListBody(
            children: <Widget>[
              Text('Go back'),
            ],
          ),
        ),
        actions: <Widget>[
          FlatButton(
            child: Text('OK'),
            onPressed: () async {

await model2.getData();

              Navigator.of(context).pop();
            },
          ),
        ],
),
      );
    },
  );
}

感谢帮助!

3 个答案:

答案 0 :(得分:2)

导航到新页面时,可以通过创建新的提供程序来轻松地在Navigator中传递提供程序。

 Navigator.of(context).push(
      MaterialPageRoute(
        builder: (BuildContext context) => Provider(
          create: (context) => InventoryItem(),
          builder: (context, child) => ProductDetails(),
        ),
      ),
    );

在这里创建新对象InventoryItem()或传递现有的提供者对象。

答案 1 :(得分:1)

我来晚了一些,但是我找到了一种解决方法,该解决方案是如何在Provider之后保持Navigator.push()的值,而不必将Provider放在{{1}上方}。

为此,我使用了库custom_navigator。它使您可以在树中的任意位置创建一个MaterialApp

您将必须创建两个分别用于NavigatorGlobalKey<NavigatorState>小部件的MaterialApp。这些键可让您控制要使用的导航器。

这里有一个小片段来说明如何做

CustomNavigator

在这里您可以从class App extends StatelessWidget { GlobalKey<NavigatorState> _mainNavigatorKey = GlobalKey<NavigatorState>(); // You need to create this key for the MaterialApp too @override Widget build(BuildContext context) { return MaterialApp( navigatorKey: _mainNavigatorKey; // Give the main key to the MaterialApp home: Provider<bool>.value( value: myProviderFunction(), child: Home(), ), ); } } class Home extends StatelessWidget { GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>(); // You need to create this key to control what navigator you want to use @override Widget build(BuildContext context) { final bool myBool = Provider.of<bool>(context); return CustomNavigator ( // CustomNavigator is from the library 'custom_navigator' navigatorKey: _navigatorKey, // Give the second key to your CustomNavigator pageRoute: PageRoutes.materialPageRoute, home: Scaffold( body: FlatButton( child: Text('Push'), onPressed: () { _navigatorKey.currentState.push( // <- Where the magic happens MaterialPageRoute( builder: (context) => SecondHome(), ), }, ), ), ), ); } } class SecondHome extends StatelessWidget { @override Widget build(BuildContext context) { final bool myBool = Provider.of<bool>(context); return Scaffold( body: FlatButton( child: Text('Pop'), onPressed: () { Novigator.pop(context); }, ), ); } } 小部件中的myBool读取值Provider,甚至在Home之后也可以使用SecondHome小部件。

但是,Android Navigator.push()按钮将从back的导航器中触发Navigator.pop()。如果要使用MaterialApp的密码,可以执行以下操作:

CustomNavigator

答案 2 :(得分:0)

您需要使Provider出现在Navigator Widget上方,以作为当前Widget的固定对象。也就是说,它必须位于MaterialApp()CupertinoApp()或您可能使用的任何Directionality()之上。

请参阅以下链接,以获取有关InheritedWidget的更多信息。

https://medium.com/@mehmetf_71205/inheriting-widgets-b7ac56dbbeb1

https://www.youtube.com/watch?v=Zbm3hjPjQMk