【问题标题】:Flutter: can't access Provider from showModalBottomSheetFlutter:无法从 showModalBottomSheet 访问 Provider
【发布时间】:2020-12-28 06:50:58
【问题描述】:

我无法从 FloatingActionButton 中的 showModalBottomSheet 访问定义在 Scaffold 上方的提供程序。

我已经这样定义了一个主页:

class HomePage extends StatelessWidget {
 @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => MyProvider(),
      builder: (context, _) {
        return Scaffold(
          body: Consumer<MyProvider>(
             builder: (context, provider, _) {
               return Text(provider.mytext); // this works fine
             }
          ),
          floatingActionButton: MyFAB(), // here is the problem
        );
      }
    )
  }
}

这是 MyFAB:

class MyFAB extends StatefulWidget {
  @override
  _MyFABState createState() => _MyFABState();
}

class _MyFABState extends State<MyFAB> {
  @override
  Widget build(BuildContext context) {
    return FloatingActionButton(
      ...
      onPressed: () => show(),
    );
  }
  
  void show() {
    showModalBottomSheet(
      ...
      context: context,
      builder: (BuildContext context) {
        return Wrap(
          children: [
            ...
            FlatButton(
              onPressed: Provider.of<MyProvider>(context, listen: false).doSomething(); //Can't do this
              Navigator.pop(context);
            )
          ],
        );
      }
    );
  }
}

错误:在此 BottomSheet 小部件上方找不到正确的 Provider

【问题讨论】:

  • 您是否尝试过传递上下文(从build 方法收到的上下文)而不是使用_MyFABState 实例的context
  • @GuilhermeMatuella 你是指 HomePage 小部件中 build 方法的上下文吗?
  • 不,_MyFabState 中的 build 方法中的 BuildContext。你创建你的FloatingActionButton

标签: flutter provider flutter-provider state-management flutter-showmodalbottomsheet


【解决方案1】:

通过将提供程序置于MaterialApp 上方进行修复,如here 所述。

底页在材料应用程序的根目录中创建。如果在材料应用程序下方声明了提供者,则底部表无法访问它,因为提供者不是小部件树中底部表的祖先。

下面的屏幕截图显示了一个小部件树:整个应用程序在 Wrapper 内,底部工作表未在 Wrapper 内创建。它被创建为MaterialApp 的另一个子元素(在本例中具有根元素Container)。

对于您的情况:

// main.dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => MyProvider(),
      builder: (context, _) {
        return MaterialApp(
          home: HomePage(),
        );
      },
    );
  }
}
// home_page.dart
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: MyFAB()
    );
  }
}

【讨论】:

    【解决方案2】:

    这是由于传递了错误的上下文引起的。将您的 FAB 包装到 Builder 小部件并将其作为 builder 属性传递。这将采用一个新的上下文并将其传递给 showModalBottomSheet。也可以onPressed: show,更简洁。

     class HomePage extends StatelessWidget {
     @override
      Widget build(BuildContext context) {
        return ChangeNotifierProvider(
          create: (_) => MyProvider(),
          builder: (context, _) {
            return Scaffold(
              body: Consumer<MyProvider>(
                 builder: (context, provider, _) {
                   return Text(provider.mytext); // this works fine
                 }
              ),
              floatingActionButton: MyFAB(context), // here is the problem
            );
          }
        )
      }
    }
    
    
    class MyFAB extends StatefulWidget {
      @override
      _MyFABState createState() => _MyFABState();
    }
    
    class _MyFABState extends State<MyFAB> {
      @override
      Widget build(BuildContext context) {
        return FloatingActionButton(
          ...
          onPressed: (context) => show(context),
        );
      }
      
      void show(ctx) {
        showModalBottomSheet(
          ...
          context: ctx,
          builder: (BuildContext context) {
            return Wrap(
              children: [
                ...
                FlatButton(
                  onPressed: () {
                  Provider.of<MyProvider>(ctx, listen: false).doSomething(); //Can't do this
                  Navigator.pop(ctx)
                  };
                )
              ],
            );
          }
        );
      }
    }
    

    【讨论】:

    • 我试过floatingActionButton: Builder(builder: (context) =&gt; MyFAB()),但它不起作用。我收到同样的错误
    • @Fabio 我在示例代码中进行了编辑。您需要以某种方式将所需的上下文传递给您的 show 函数。这应该有效。如果没有,请分享您的整个代码,我将对其进行编辑。我还修复了您的 FlatButton onPressed 属性。您所做的两件事必须在一个函数中并传递给按钮。
    • 在 MyFAB 中没有任何构造函数的情况下,您是如何从 HomePage 传递上下文参数的?
    • 我没有对此进行测试,因为大部分代码都不完整。如果您遇到错误,请尝试在您的主页中定义 show() 并将其传递给您的晶圆厂,而不是为晶圆厂创建一个全新的文件
    • 我为 FAB 创建了一个新文件,因为它比这更复杂,但是,我只是将上下文从 HomePage 传递到 MyFAB 并且它可以工作
    【解决方案3】:

    解决方案

    主页:

    class HomePage extends StatelessWidget {
     @override
      Widget build(BuildContext context) {
        return ChangeNotifierProvider(
          create: (_) => MyProvider(),
          builder: (context, _) {
            return Scaffold(
              body: Consumer<MyProvider>(
                 builder: (context, provider, _) {
                   return Text(provider.mytext); // this works fine
                 }
              ),
              floatingActionButton: MyFAB(context), // here is the problem
            );
          }
        )
      }
    }
    

    我的FAB:

    class MyFAB extends StatefulWidget {
    final BuildContext ctx;
    
    MyFAB(this.ctx)
    
      @override
      _MyFABState createState() => _MyFABState();
    }
    
    class _MyFABState extends State<MyFAB> {
      @override
      Widget build(BuildContext context) {
        return FloatingActionButton(
          ...
          onPressed: () => show(),
        );
      }
      
      void show() {
        showModalBottomSheet(
          ...
          context: context,
          builder: (BuildContext context) {
            return Wrap(
              children: [
                ...
                FlatButton(
                  onPressed: Provider.of<MyProvider>(widget.ctx, listen: false).doSomething(); //Can't do this
                  Navigator.pop(context);
                )
              ],
            );
          }
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-27
      • 2022-01-16
      • 2020-11-03
      • 2022-01-16
      • 2020-06-13
      • 2016-10-16
      • 2020-01-17
      • 1970-01-01
      相关资源
      最近更新 更多