来自完整开发人员指南课程 Udemy 165 的 Flutter Bloc 模式问题

Posted

技术标签:

【中文标题】来自完整开发人员指南课程 Udemy 165 的 Flutter Bloc 模式问题【英文标题】:Flutter Bloc pattern question from The complete developers guide course Udemy 165 【发布时间】:2021-12-20 02:04:11 【问题描述】:

我对 Udemy 的这门课程有疑问,我试图在 Flutter 中设置 Bloc 模式以进行身份​​验证。问题是,当我从 StreamBuilder 的 snapshot.error 中键入所需的“@”时,我从一开始就得到了一个空值。它已设置好,所以我应该会收到一条错误消息,直到我输入“@”,然后该消息就会消失。我有三个相关文件:loginscreen、bloc 和验证器。你们认为这里会出现什么问题?

登录界面:

class LoginScreen extends StatelessWidget 
  @override
  Widget build(context) 
    return Container(
      margin: EdgeInsets.all(20.0),
      child: Column(
        children: [
          emailField(),
          passwordField(),
          //const SizedBox(height: 25.0),
          Container(margin: const EdgeInsets.only(top: 25.0)),
          submitButton(),
        ],
      ),
    );
  

  Widget emailField() 
    //Listener for streams rebuilds builder function when found

    return StreamBuilder(
        stream: bloc.email,
        //snapshot contains the value from the stream
        builder: (context, AsyncSnapshot<String>? snapshot) 
          return TextField(
            onChanged: (newValue) 
              print(newValue);
              bloc.changeEmail(newValue);
            ,
            keyboardType: TextInputType.emailAddress,
            decoration: InputDecoration(
              hintText: 'you@example.com',
              labelText: 'Email Address',
              //This is null for some reason. Something is not right here
              //First it shows error because no @ and when pressed I get null
              errorText: snapshot!.error.toString(),
            ),
          );
        );
  

Bloc:

class Bloc with Validators 
  //We are working with Strings in the Streamcontrollers (marked with String type)
  final _email = StreamController<String>();
  final _password = StreamController<String>();

  //Annotation with generic type in front. Not required though
  // Add data to stream (access to stream)
  // Apply the validation transform created
  Stream<String> get email => _email.stream.transform(validateEmail);
  Stream<String> get password => _password.stream.transform(validatePassword);

  // Change data (access to sink)
  Function(String) get changeEmail => _email.sink.add;
  Function(String) get changePassword => _password.sink.add;

  dispose() 
    _email.close();
    _password.close();
  


final bloc = Bloc();

Validators:

class Validators 
  final validateEmail =
      StreamTransformer<String, String>.fromHandlers(handleData: (email, sink) 
    if (email.contains('@')) 
      sink.add(email);
     else 
      sink.addError('Enter a valid email!');
    
  );

  final validatePassword = StreamTransformer<String, String>.fromHandlers(
      handleData: (password, sink) 
    if (password.length > 7) 
      sink.add(password);
     else 
      sink.addError('You must be at least 8 characters!');
    
  );

更改为:

errorText: 快照?.error?.toString() ??快照?.数据,

【问题讨论】:

【参考方案1】:

你总是在这里阅读流的错误:

    errorText: snapshot!.error.toString(),

但你只在这个 else 中添加错误:

    if (email.contains('@')) 
      sink.add(email);
     else 
      sink.addError('Enter a valid email!');
    

您可以尝试替换此值的读取方式:

              //This is null for some reason. Something is not right here
              //First it shows error because no @ and when pressed I get null
              errorText: snapshot?.error?.toString() ?? snapshot?.data,

这样,如果没有错误,errorText就会得到流的数据。

更新: 如果你想让这个消息在 @ 被插入后完全消失,你可以先看看 errorText 是如何工作的。来自 Flutter 的 InptuDecorator 源码:

  /// Text that appears below the [InputDecorator.child] and the border.
  ///
  /// If non-null, the border's color animates to red and the [helperText] is
  /// not shown.
  ///
  /// In a [TextFormField], this is overridden by the value returned from
  /// [TextFormField.validator], if that is not null.
  final String? errorText;

因此,如果您不向其传递字符串,该消息将被隐藏。这段代码发生了什么:

    errorText: snapshot!.error.toString(),

是这样的:null.toString();。 Dart 可以并将 null 解析为字符串,并将其转换为以 null 为内容的字符串。 为了解决这个问题,我们在错误后添加一个? 标记,如下所示: snapshot?.error?.toString(),。现在,toString() 只会在 error 不为空时被调用。

提示:一定要探索您正在使用的小部件的源代码。他们被广泛评论,你可以比谷歌随机的东西更快地获取信息?

【讨论】:

感谢您的回复 Tales Barreto!是的,我尝试了该解决方案并且它有效,但仍有一个问题是即使 @ 存在,文本也是红色而不是蓝色(如错误文本)。我猜那是因为错误文本为空,他从那里读取了 snapshot.data。 嘿!我刚刚更新了我的答案;-) 是的,感谢您的洞察力!我已阅读该文档,我认为问题在于,当您开始键入时,它会在按下 @ 后转到 else(错误消息已设置),而错误变为 null(但仍处于错误状态)并且快照?.data 已设置到 errorText 并且当我键入每个字符时,现在可以看到每个字符,直到我删除 @ 并且再次看到错误消息(如果我不全部删除,则始终为红色)。这让我有点难以理解!

以上是关于来自完整开发人员指南课程 Udemy 165 的 Flutter Bloc 模式问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用“标题”更新列表视图

如何成为一名Web前端开发人员?入行学习完整指南

程序猿菜鸟必备——作为独立开发人员怎样系统的学习编程

如何学习ReactJS:初学者完整指南

如何学习ReactJS:初学者完整指南

Flutter完整开发实战详解(十九 Android 和 iOS 打包提交审核指南)