K.c*_*him 8 flutter flutter-packages flutter-bloc
我在 Flutter 应用程序中使用 flutter_bloc 4.0.0,我使用 Felix Angelov 的示例(https://medium.com/flutter-community/firebase-login-with-flutter-bloc-47455e6047b0)来实现登录或使用块模式的登录流程。它工作正常,但在我更新我的 Flutter 并检查我的代码后,我发现了一系列错误。我不明白他们为什么要来,因为上周一切都很好。小部件的构建方法中的块的实现对我来说突然变得错误了。我收到错误:
\n\n1.“BlocListener的\xe2\x80\x98A值类型不能从方法构建中返回\xe2\x80\x99,因为它有一个widget的返回类型”
\n\n第一个错误的代码
\n\nclass LoginForm extends StatefulWidget {\n final UserRepository _userRepository;\n\n LoginForm({Key key, @required UserRepository userRepository})\n : assert(userRepository != null),\n _userRepository = userRepository,\n super(key: key);\n\n State<LoginForm> createState() => _LoginFormState();\n}\n\nclass _LoginFormState extends State<LoginForm> {\n final TextEditingController _emailController = TextEditingController();\n final TextEditingController _passwordController = TextEditingController();\n\n LoginBloc _loginBloc;\n\n UserRepository get _userRepository => widget._userRepository;\n\n bool get isPopulated =>\n _emailController.text.isNotEmpty && _passwordController.text.isNotEmpty;\n\n bool isLoginButtonEnabled(LoginState state) {\n return state.isFormValid && isPopulated && !state.isSubmitting;\n }\n\n @override\n void initState() {\n super.initState();\n _loginBloc = BlocProvider.of<LoginBloc>(context);\n _emailController.addListener(_onEmailChanged);\n _passwordController.addListener(_onPasswordChanged);\n }\n\n @override\n Widget build(BuildContext context) {\n return BlocListener<LoginBloc, LoginState>(\n listener: (context, state) {\n if (state.isFailure) {\n Scaffold.of(context)\n ..hideCurrentSnackBar()\n ..showSnackBar(\n SnackBar(\n content: Row(\n mainAxisAlignment: MainAxisAlignment.spaceBetween,\n children: [Text(\'Login Failure\'), Icon(Icons.error)],\n ),\n backgroundColor: Colors.red,\n ),\n );\n }\n if (state.isSubmitting) {\n Scaffold.of(context)\n ..hideCurrentSnackBar()\n ..showSnackBar(\n SnackBar(\n content: Row(\n mainAxisAlignment: MainAxisAlignment.spaceBetween,\n children: [\n Text(\'Logging In...\'),\n CircularProgressIndicator(),\n ],\n ),\n ),\n );\n }\n if (state.isSuccess) {\n BlocProvider.of<AuthenticationBloc>(context).add(LoggedIn());\n }\n },\n child: BlocBuilder<LoginBloc, LoginState>(\n builder: (context, state) {\n return Padding(\n padding: EdgeInsets.all(20.0),\n child: Form(\n child: ListView(\n children: <Widget>[\n Padding(\n padding: EdgeInsets.symmetric(vertical: 20),\n child: Image.asset(\'assets/flutter_logo.png\', height: 200),\n ),\n Container(\n margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 20.0),\n height: 45.0,\n child: TextFormField(\n controller: _emailController,\n style: TextStyle(\n fontFamily: \'Avenir-Medium\',\n fontSize: 12.0,\n color: Colors.black,\n ),\n decoration: InputDecoration(\n border: OutlineInputBorder(\n borderRadius: const BorderRadius.all(\n const Radius.circular(7.0),\n ),\n borderSide: BorderSide(\n color: Colors.grey[200],\n width: 7.0,\n )),\n labelText: \'email\',\n ),\n keyboardType: TextInputType.emailAddress,\n autovalidate: true,\n autocorrect: false,\n validator: (_) {\n return !state.isEmailValid ? \'Invalid Email\' : null;\n },\n ),\n ),\n Container(\n height: 45.0,\n child: TextFormField(\n style: TextStyle(\n fontFamily: \'Avenir-Medium\',\n fontSize: 12.0,\n color: Colors.black,\n ),\n controller: _passwordController,\n decoration: InputDecoration(\n border: OutlineInputBorder(\n borderRadius: const BorderRadius.all(\n const Radius.circular(7.0),\n ),\n borderSide: BorderSide(\n color: Colors.grey[200],\n width: 0.0,\n )),\n labelText: \'password\',\n ),\n obscureText: true,\n autovalidate: true,\n autocorrect: false,\n validator: (_) {\n return !state.isPasswordValid ? \'Invalid Password\' : null;\n },\n ),\n ),\n Padding(\n padding: EdgeInsets.symmetric(vertical: 20),\n child: Column(\n crossAxisAlignment: CrossAxisAlignment.stretch,\n children: <Widget>[\n LoginButton(\n onPressed: _onFormSubmitted,\n\n// isLoginButtonEnabled(state)\n// ? _onFormSubmitted\n// : null,\n ),\n GoogleLoginButton(),\n AppleSignInButton(),\n CreateAccountButton(userRepository: _userRepository),\n ForgotPasswordButton()\n ],\n ),\n ),\n ],\n ),\n ),\n );\n },\n ),\n );\n }\n\n @override\n void dispose() {\n _emailController.dispose();\n _passwordController.dispose();\n super.dispose();\n }\n\n void _onEmailChanged() {\n _loginBloc.add(\n EmailChanged(email: _emailController.text),\n );\n }\n\n void _onPasswordChanged() {\n _loginBloc.add(\n PasswordChanged(password: _passwordController.text),\n );\n }\n\n void _onFormSubmitted() {\n _loginBloc.add(\n LoginWithCredentialsPressed(\n email: _emailController.text,\n password: _passwordController.text,\n ),\n );\n }\n}\n\nthe code for the second error above is as follows\n\nvoid main() {\n WidgetsFlutterBinding.ensureInitialized();\n BlocSupervisor.delegate = SimpleBlocDelegate();\n final UserRepository userRepository = UserRepository();\n runApp(\n BlocProvider(\n create: (context) => AuthenticationBloc(\n userRepository: userRepository,\n )..add(AppStarted()),\n child: App(userRepository: userRepository),\n ),\n );\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n
Tho*_*mas 26
也许我的回答对你来说有点过时,但我希望它能对其他人有所帮助。
首先,BlocBuilder/BlocListener 应该在相应的 BlocProvider 的范围内。
您应该在无状态/有状态小部件的构建方法中返回 BlocBuilder。如果你想结合 BlocListener 和 BlocBuilder,你可以使用 BlocConsumer 小部件。此外,您可以添加参数 buildWhen 来指定 BlocBuilder 是否应根据传入状态重建您的小部件。这是一个例子:
class __ScreenWidgetState extends State<Screen> {
@override
Widget build(BuildContext context) {
return BlocConsumer<ScreenBloc, ScreenState>(
buildWhen: (previousState, state) {
return state is! DontBuild;
},
builder: (BuildContext context, state) {
return Text(state.text);
},
listener: (BuildContext context, state) {
if (state is ShowFlushbar) {
showFlushBar(context: context, message: state.text);
}
},
);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,我们的 Screen Widget 应该位于 ScreenBloc 的范围内(作为它的子级)。我们可以通过以下方式实现这一点:
BlocProvider<ScreenBloc>(
create: (context) => ScreenBloc(),
child: Screen(),
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
36508 次 |
| 最近记录: |