首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过Navigator通过提供者?

如何通过Navigator通过提供者?
EN

Stack Overflow用户
提问于 2019-08-21 19:22:56
回答 3查看 14.3K关注 0票数 15

我需要pass提供者(Model2)从homepagePage2,所以当用户返回homepage (onWillPop)时,我可以从提供者(Model2)进行API调用并更新homepage

但是,当我调用_onPaidBackPress(context)时,会出现错误:

未处理的异常:错误:无法找到此消费者Widget之上的正确提供程序

主页中的StatefulWidget

代码语言:javascript
复制
@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)));

在Page2中:

代码语言:javascript
复制
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();
            },
          ),
        ],
),
      );
    },
  );
}

谢谢你帮忙!

EN

回答 3

Stack Overflow用户

发布于 2020-09-01 14:35:57

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

代码语言:javascript
复制
 Navigator.of(context).push(
      MaterialPageRoute(
        builder: (BuildContext context) => Provider(
          create: (context) => InventoryItem(),
          builder: (context, child) => ProductDetails(),
        ),
      ),
    );

这里要么创建一个新的对象InventoryItem(),要么传递现有的提供程序对象。

票数 15
EN

Stack Overflow用户

发布于 2019-08-21 19:50:35

您需要使提供程序出现在Navigator Widget之上,才能成为当前Widget的锚。这意味着,它必须驻留在MaterialApp()CupertinoApp()或您可能使用的任何Directionality()之上。

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

71205/inheriting-widgets-b7ac56dbbeb1

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

票数 3
EN

Stack Overflow用户

发布于 2020-08-05 17:18:34

我有点晚了,但我找到了一个解决方案,说明如何使Provider的值在Navigator.push()之后存活,而不必将Provider置于MaterialApp之上。

为此,我使用了库custom_navigator。它允许您在树中的任何地方创建Navigator

您必须创建两种不同的GlobalKey<NavigatorState>,它们将提供给MaterialAppCustomNavigator小部件。这些键将允许您控制您想要使用的导航器。

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

代码语言:javascript
复制
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读取值,但也可以读取SecondHome小部件,即使在Navigator.push()之后也是如此。

然而,Android back按钮将触发来自MaterialApp导航器的Navigator.pop()。如果您想使用CustomNavigator的一个,可以这样做:

代码语言:javascript
复制
// In the Home Widget insert this
   ...
   @override
   Widget build(BuildContext context) {
      return WillPopScope(
         onWillPop: () async {
            if (_navigatorKey.currentState.canPop()) {
               _navigatorKey.currentState.pop();  // Use the custom navigator when available
               return false;  // Don't pop the main navigator
            } else {
               return true;  // There is nothing to pop in the custom navigator anymore, use the main one
            }
         },
         child: CustomNavigator(...),
      );
   }
   ...
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57598029

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档