Flutter - 提供者

Flutter - Provider

我正在尝试创建以下小部件,在其中按下一个按钮,用户应该被重定向到 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

不幸的是,我对提供商不太了解,所以如果有人能解释哪里出了问题以及我该如何解决,我将不胜感激。谢谢

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

调用此方法时,提供程序包将使用 MainGameScreen 的 context 并查找其上方是否存在类型为 AuthBlocProvider Widget。如果找不到包,将抛出该异常。

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

所以我认为您应该在 MainGameScreen 小部件上方添加一个类型为 AuthBlocProvider,它通常如下所示:

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<AuthBloc>).

类型

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 之上有了一个提供者 ;)。请记住,添加小部件测试非常困难,因此在使用它之前请三思。

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