【问题标题】:Flutter - Provider颤振 - 提供者
【发布时间】:2021-11-01 21:08:05
【问题描述】:

我正在尝试创建以下小部件,在该小部件中按下按钮,用户应重定向到 MainGameScreen()。

Widget quitGame(BuildContext context) {
showDialog(
    context: context,
    builder: (BuildContext context) {
      return Dialog(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(10),
        ),
        elevation: 0,
        backgroundColor: Colors.transparent,
        child: Stack(
          children: <Widget>[
            Container(
              padding:
                  EdgeInsets.only(left: 20, top: 30, right: 20, bottom: 20),
              margin: EdgeInsets.only(top: 45),
              decoration: BoxDecoration(
                  shape: BoxShape.rectangle,
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(20),
                  boxShadow: [
                    BoxShadow(
                        color: Colors.black,
                        offset: Offset(0, 10),
                        blurRadius: 10),
                  ]),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Text(
                    "QUIT GAME",
                    textScaleFactor: 1,
                    style: TextStyle(
                        fontSize: 40, fontWeight: FontWeight.w600),
                  ),
                  SizedBox(
                    height: 15,
                  ),
                  Text(
                    "Are you sure you want to leave the game?",
                    textScaleFactor: 1,
                    style: TextStyle(fontSize: 14),
                    textAlign: TextAlign.center,
                  ),
                  SizedBox(
                    height: 10,
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Align(
                        alignment: Alignment.bottomCenter,
                        child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              primary: Color(0xFFec4688),
                            ),
                            onPressed: () {
                              Navigator.of(context).pop();
                            },
                            child: Text("NO",
                                textScaleFactor: 1,
                                style: TextStyle(fontSize: 20))),
                      ),
                      Align(
                        alignment: Alignment.bottomCenter,
                        child: ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              primary: Color(0xFF1fd281),
                            ),
                            onPressed: () {
                              roundTimer.cancel();
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                  builder: (context) => MainGameScreen(),
                                ),
                              );
                            },
                            child: Text("YES",
                                textScaleFactor: 1,
                                style: TextStyle(fontSize: 20))),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      );
    });
}

但是当我这样做时,我收到以下错误:

════════ Exception caught by widgets library ═══════════════════════════════════
The following ProviderNotFoundException was thrown building Builder:
Error: Could not find the correct Provider<AuthBloc> above this MainGameScreen Widget

不幸的是,我对提供者没有很好的了解,所以如果有人能解释出了什么问题以及如何解决它,我将不胜感激。谢谢

【问题讨论】:

    标签: flutter provider


    【解决方案1】:

    我认为在 MainGameScreen 中,您使用了如下代码:
    final bloc = Provider.of&lt;AuthBloc&gt;(context, listen: false,);

    调用这个的时候,provider包会使用MainGameScreen的context,查找上面是否有类型为AuthBlocProviderWidget。如果包找不到,就会抛出该异常。

    The following ProviderNotFoundException was thrown building Builder:
    Error: Could not find the correct Provider<AuthBloc> above this MainGameScreen Widget
    

    所以我认为你应该在MainGameScreen 小部件上方添加一个Provider 类型为AuthBloc,它通常看起来像这样:

    Provider<AuthBloc>(
    create: (context) => AuthBloc(),
    dispose: (context, bloc) => bloc.dispose(), // remove it if there is no dispose method in your BLoC
    child: MainGameScreen(),
    ),
    

    您可以在MainGameScreen() 上方的任意位置添加此Provider,并且它还必须具有AuthBloc (Provider&lt;AuthBloc&gt;) 的类型。

    【讨论】:

    • @Tran 是的,我在 MainGameScreen() 中听过:false。但我不明白在哪里放置这个 Provider。 MainGameScreen 是一个有状态的小部件。如果我将它放在小部件之外,则会出错。
    【解决方案2】:

    MainGameScreen Widget 必须是 Provider 小部件的后代。但是在这里,您使用MaterialPageRoute 将新路由推送到您的应用程序,因此MainGameScreen 将位于小部件树的一个新的独立分支中,它的唯一父级是Material App Widget。所以有两种解决方案:

    1. Place the ProviderWidget above the MaterialApp Widget. Ex:
          Provider<AuthBloc>(   
            create: (context) => AuthBloc(),  
            dispose: (context, bloc) => bloc.dispose(), // remove it if there is no dispose method in your BLoC
            child: MaterialApp(),  
            ),
    
    
    
    2. A trick, which is very useful but really hard to test and manage: Add a `static` method which look like this :
        
            class MainGameScreen extends StatefulWidget {
                      static Widget create(BuildContext context) {
                        return Provider<AuthBloc>(
                          create: (_) => AuthBloc(),
                          child: MainGameScreen(),
                        );
                      } 
    

    当我们使用MaterialPageRoute推送时,使用:

     MaterialPageRoute(
          builder: (context) => MainGameScreen.create(context),
        ),
    

    通过这个解决方案,我们在MainGameScreen 上方有一个提供者;)。请记住,添加小部件测试非常困难,因此在使用前请三思。

    对不起我之前的愚蠢解释!

    【讨论】:

      猜你喜欢
      • 2020-05-10
      • 2019-12-08
      • 2022-01-15
      • 2020-06-04
      • 2021-06-18
      • 1970-01-01
      • 2020-12-24
      • 1970-01-01
      • 2022-08-19
      相关资源
      最近更新 更多