无法使用 BlockBuilder() 和 TextField() 的 onChanged 属性 更新状态。 [Flutter_Bloc]

Failed to update the state using BlockBuilder() and TextField()'s onChanged property. [Flutter_Bloc]

我正在尝试做一个简单的表单验证模型,到目前为止,我无法使用 TextField() 的 onChanged 属性.[=15 在 BlocBuilder() 下更新我的状态=]

这是我的 BlocProvider()

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Log me in',
      home: Scaffold(
        body: BlocProvider<LoginBloc>(
          create: (context) => LoginBloc(),
          child: LoginScreen(),
        ),
      ),
    );
  }
}

这是需要在输入更改时更新的主文件。 '$snapshot' 应该根据其当前状态产生来自 LoginBloc 的内容,但看起来它不会在在线更改 StreamBuilder()

上自行重建
lass LoginScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);
    return BlocBuilder<LoginBloc, String>(
        bloc: LoginBloc(),
        builder: (context, snapshot) {
          return Container(
            margin: EdgeInsets.all(10),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                // emailField(bloc),
                TextField(
                  onChanged: (_) => bloc.add(LoginEvent.username),
                  keyboardType: TextInputType.emailAddress,
                  decoration: InputDecoration(
                    hintText: 'example@email.com',
                    labelText: 'Email Address',
                    errorText: '$snapshot',
                  ),
                ),
                // passwordField(bloc),
                TextField(
                  onChanged: (_) => bloc.add(LoginEvent.password),
                  keyboardType: TextInputType.visiblePassword,
                  decoration: InputDecoration(
                    hintText: 'Password',
                    labelText: 'Password',
                    errorText: '$snapshot',
                  ),
                ),
                SizedBox(
                  height: 25,
                ),
                // submitButton(),
              ],
            ),
          );
        });
  }

这是我的 LoginBloc()

class LoginBloc extends Bloc<LoginEvent, String> {
  get initialState => '';

  Stream<String> mapEventToState(LoginEvent event) async* {
    switch (event) {
      case LoginEvent.username:
        if (state.contains('@')) {
          yield 'Approved';
        } else {
          yield 'Please retry';
        }
        break;
      case LoginEvent.password:
        if (state.length > 3) {
          yield 'Nice password';
        }
        yield "Please retry";
    }
  }
}

谢谢

看起来问题出在这一行:

final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);

您在错误的上下文中访问了该集团。删除该行并在要访问 LoginBloc:

时直接使用 BlocProvider
onChanged: (_) => BlocProvider.of<LoginBloc>(context).add(LoginEvent.username),

您的应用中有两个不同的 LoginBloc 实例。一个由 BlocProvider 创建并传递,第二个由您在 BlocBuilder.

中创建

问题是您正在将事件添加到 BlocProvider's 集团中,而 BlocBuilder 正在监听另一个集团。

要解决此问题,您可以这样做

Widget build(BuildContext context) {
  final LoginBloc bloc = BlocProvider.of<LoginBloc>(context);
  return BlocBuilder<LoginBloc, String>(
    bloc: bloc,      // Pass the above bloc instance 
    builder: (context, snapshot) {
      // rest as it is
    }
  )
}

奖励:- 您可以跳过 bloc: bloc,因为它是一个可选参数,如果没有提供,它会使用 BlocProvider

从树中自动找到

您还需要以不同的方式管理状态,否则在其中一个字段中输入将在两个字段中显示错误