gpt4 book ai didi

flutter - 如何在 Flutter App 中正确使用 BlocListener 和 BlocProvider

转载 作者:行者123 更新时间:2023-12-04 12:05:44 24 4
gpt4 key购买 nike

我在我的 Flutter 应用程序中使用了 flutter_bloc 4.0.0,我使用了 Felix Angelov ( https://medium.com/flutter-community/firebase-login-with-flutter-bloc-47455e6047b0 ) 的示例来使用 bloc 模式实现登录或登录流程。它工作正常,但在我更新 Flutter 并稍后检查我的代码后,我发现了一系列错误。我不明白他们为什么要来,因为上周一切都很好。在小部件的构建方法中实现 bloc 突然对我来说是错误的。我收到错误:

1.“‘BlocListener的值类型不能从方法build中返回,因为它有一个widget的返回类型”

  • ‘BlocProvider> 的值类型无法从方法构建中返回,因为它具有小部件的返回类型’

  • 第一个错误的代码
    class LoginForm extends StatefulWidget {
    final UserRepository _userRepository;

    LoginForm({Key key, @required UserRepository userRepository})
    : assert(userRepository != null),
    _userRepository = userRepository,
    super(key: key);

    State<LoginForm> createState() => _LoginFormState();
    }

    class _LoginFormState extends State<LoginForm> {
    final TextEditingController _emailController = TextEditingController();
    final TextEditingController _passwordController = TextEditingController();

    LoginBloc _loginBloc;

    UserRepository get _userRepository => widget._userRepository;

    bool get isPopulated =>
    _emailController.text.isNotEmpty && _passwordController.text.isNotEmpty;

    bool isLoginButtonEnabled(LoginState state) {
    return state.isFormValid && isPopulated && !state.isSubmitting;
    }

    @override
    void initState() {
    super.initState();
    _loginBloc = BlocProvider.of<LoginBloc>(context);
    _emailController.addListener(_onEmailChanged);
    _passwordController.addListener(_onPasswordChanged);
    }

    @override
    Widget build(BuildContext context) {
    return BlocListener<LoginBloc, LoginState>(
    listener: (context, state) {
    if (state.isFailure) {
    Scaffold.of(context)
    ..hideCurrentSnackBar()
    ..showSnackBar(
    SnackBar(
    content: Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: [Text('Login Failure'), Icon(Icons.error)],
    ),
    backgroundColor: Colors.red,
    ),
    );
    }
    if (state.isSubmitting) {
    Scaffold.of(context)
    ..hideCurrentSnackBar()
    ..showSnackBar(
    SnackBar(
    content: Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: [
    Text('Logging In...'),
    CircularProgressIndicator(),
    ],
    ),
    ),
    );
    }
    if (state.isSuccess) {
    BlocProvider.of<AuthenticationBloc>(context).add(LoggedIn());
    }
    },
    child: BlocBuilder<LoginBloc, LoginState>(
    builder: (context, state) {
    return Padding(
    padding: EdgeInsets.all(20.0),
    child: Form(
    child: ListView(
    children: <Widget>[
    Padding(
    padding: EdgeInsets.symmetric(vertical: 20),
    child: Image.asset('assets/flutter_logo.png', height: 200),
    ),
    Container(
    margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 20.0),
    height: 45.0,
    child: TextFormField(
    controller: _emailController,
    style: TextStyle(
    fontFamily: 'Avenir-Medium',
    fontSize: 12.0,
    color: Colors.black,
    ),
    decoration: InputDecoration(
    border: OutlineInputBorder(
    borderRadius: const BorderRadius.all(
    const Radius.circular(7.0),
    ),
    borderSide: BorderSide(
    color: Colors.grey[200],
    width: 7.0,
    )),
    labelText: 'email',
    ),
    keyboardType: TextInputType.emailAddress,
    autovalidate: true,
    autocorrect: false,
    validator: (_) {
    return !state.isEmailValid ? 'Invalid Email' : null;
    },
    ),
    ),
    Container(
    height: 45.0,
    child: TextFormField(
    style: TextStyle(
    fontFamily: 'Avenir-Medium',
    fontSize: 12.0,
    color: Colors.black,
    ),
    controller: _passwordController,
    decoration: InputDecoration(
    border: OutlineInputBorder(
    borderRadius: const BorderRadius.all(
    const Radius.circular(7.0),
    ),
    borderSide: BorderSide(
    color: Colors.grey[200],
    width: 0.0,
    )),
    labelText: 'password',
    ),
    obscureText: true,
    autovalidate: true,
    autocorrect: false,
    validator: (_) {
    return !state.isPasswordValid ? 'Invalid Password' : null;
    },
    ),
    ),
    Padding(
    padding: EdgeInsets.symmetric(vertical: 20),
    child: Column(
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: <Widget>[
    LoginButton(
    onPressed: _onFormSubmitted,

    // isLoginButtonEnabled(state)
    // ? _onFormSubmitted
    // : null,
    ),
    GoogleLoginButton(),
    AppleSignInButton(),
    CreateAccountButton(userRepository: _userRepository),
    ForgotPasswordButton()
    ],
    ),
    ),
    ],
    ),
    ),
    );
    },
    ),
    );
    }

    @override
    void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
    }

    void _onEmailChanged() {
    _loginBloc.add(
    EmailChanged(email: _emailController.text),
    );
    }

    void _onPasswordChanged() {
    _loginBloc.add(
    PasswordChanged(password: _passwordController.text),
    );
    }

    void _onFormSubmitted() {
    _loginBloc.add(
    LoginWithCredentialsPressed(
    email: _emailController.text,
    password: _passwordController.text,
    ),
    );
    }
    }

    the code for the second error above is as follows

    void main() {
    WidgetsFlutterBinding.ensureInitialized();
    BlocSupervisor.delegate = SimpleBlocDelegate();
    final UserRepository userRepository = UserRepository();
    runApp(
    BlocProvider(
    create: (context) => AuthenticationBloc(
    userRepository: userRepository,
    )..add(AppStarted()),
    child: App(userRepository: userRepository),
    ),
    );
    }

    image for the error

    the second error

    最佳答案

    也许我的回答对你来说有点过时,但我希望它能帮助别人。
    首先,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);
    }
    },
    );
    }
    }
    因此,我们的 Screen Widget 应该在 ScreenBloc 的范围内(作为它的子项)。我们可以通过以下方式实现这一点:
    BlocProvider<ScreenBloc>(
    create: (context) => ScreenBloc(),
    child: Screen(),
    );

    关于flutter - 如何在 Flutter App 中正确使用 BlocListener 和 BlocProvider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62328609/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com