[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XSljASWk-1620260140025)(https://ducafecat.tech/2021/05/06/translation/mastering-flutter-bloc-pattern-for-login-part-1/2021-05-06-08-01-18.png)]

原文

https://medium.com/theotherdev-s/mastering-flutter-bloc-pattern-for-login-part-1-94082e139725

前言

首先,由于这不是一个基本的教程,我们理所当然地认为这是一个路线的知识,我们也包含了一点点的 validationformoz 包来创建可重用的模型; 这不是本教程的目的,以显示这将如何工作,您将看到这在下一个教程。对于登录部分,出于教程的目的,我们还使用了 BLoC (Cubit) 的子集,因此您将看到这两者之间的区别。

代码,可以先阅读代码,再看文档

https://github.com/Alessandro-v/bloc_login

参考

  • https://pub.flutter-io.cn/packages/equatable
  • https://pub.flutter-io.cn/packages/validation
  • https://pub.flutter-io.cn/packages/flutter_bloc
  • https://pub.flutter-io.cn/packages/formoz

正文

开始

在我们开始之前,让我们在 pubspec.yaml 中添加一些必要的包:

equatable: ^2.0.0
flutter_bloc: ^7.0.0
formz: ^0.3.2

添加 equatable 包只会使您的工作更加容易,但是如果您想手动比较类的实例,只需要重写 “==” 和 hashCode。

登录状态

让我们从一个包含表单状态和所有字段状态的类开始:

class LoginState extends Equatable {const LoginState({this.email = const Email.pure(),this.password = const Password.pure(),this.status = FormzStatus.pure,this.exceptionError,});final Email email;final Password password;final FormzStatus status;final String exceptionError;@overrideList<Object> get props => [email, password, status, exceptionError];LoginState copyWith({Email email,Password password,FormzStatus status,String error,}) {return LoginState(email: email ?? this.email,password: password ?? this.password,status: status ?? this.status,exceptionError: error ?? this.exceptionError,);}
}

现在让我们创建我们的 LoginCubit,它将负责执行逻辑,例如通过 emit 获取电子邮件和输出新状态:

class LoginCubit extends Cubit<LoginState> {LoginCubit() : super(const LoginState());void emailChanged(String value) {final email = Email.dirty(value);emit(state.copyWith(email: email,status: Formz.validate([email,state.password]),));}void passwordChanged(String value) {final password = Password.dirty(value);emit(state.copyWith(password: password,status: Formz.validate([state.email,password]),));}Future<void> logInWithCredentials() async {if (!state.status.isValidated) return;emit(state.copyWith(status: FormzStatus.submissionInProgress));try {await Future.delayed(Duration(milliseconds: 500));emit(state.copyWith(status: FormzStatus.submissionSuccess));} on Exception catch (e) {emit(state.copyWith(status: FormzStatus.submissionFailure, error: e.toString()));}}
}

但是我们如何将腕尺与我们的用户界面连接起来呢?下面是对 BlocProvider 的解救,这是一个小部件,它使用: BlocProvider.of<logincubit>(context) 为其子部件提供一个区块

BlocProvider(create: (_) => LoginCubit(),child: LoginForm(),
),

登入表格

既然现在似乎都在他自己的地方,是时候解决我们的最后一块 puzzle,整个用户界面

class LoginForm extends StatelessWidget {const LoginForm({Key key}) : super(key: key);@overrideWidget build(BuildContext context) {return BlocConsumer<LoginCubit, LoginState>(listener: (context, state) {if (state.status.isSubmissionFailure) {print('submission failure');} else if (state.status.isSubmissionSuccess) {print('success');}},builder: (context, state) => Stack(children: [Positioned.fill(child: SingleChildScrollView(padding: const EdgeInsets.fromLTRB(38.0, 0, 38.0, 8.0),child: Container(child: Column(crossAxisAlignment: CrossAxisAlignment.stretch,mainAxisAlignment: MainAxisAlignment.start,children: [_WelcomeText(),_EmailInputField(),_PasswordInputField(),_LoginButton(),_SignUpButton(),],),),),),state.status.isSubmissionInProgress? Positioned(child: Align(alignment: Alignment.center,child: CircularProgressIndicator(),),) : Container(),],));}
}

为了对 Cubit 发出的新状态做出反应,我们需要将我们的表单包裹在一个 BlocConsumer 中,现在我们将暴露一个监听者和一个建造者。

  • Listener

这里我们将监听状态更改,例如,在响应 API 调用时显示错误或执行导航。

  • Builder

在这里,我们将显示 ui 反应状态的变化,我们的 Cubit

用户界面

我们的用户界面由一个列和 5 个子元素组成,但是我们只展示 2 个简短的小部件:

class _EmailInputField extends StatelessWidget {@overrideWidget build(BuildContext context) {return BlocBuilder<LoginCubit, LoginState>(buildWhen: (previous, current) => previous.email != current.email,builder: (context, state) {return AuthTextField(hint: 'Email',key: const Key('loginForm_emailInput_textField'),keyboardType: TextInputType.emailAddress,error: state.email.error.name,onChanged: (email) => context.read<LoginCubit>().emailChanged(email),);},);}
}
class _LoginButton extends StatelessWidget {const _LoginButton({Key key}) : super(key: key);@overrideWidget build(BuildContext context) {return BlocBuilder<LoginCubit, LoginState>(buildWhen: (previous, current) => previous.status != current.status,builder: (context, state) {return CupertinoButton(child: Text('Login'),onPressed: state.status.isValidated? () => context.read<LoginCubit>().logInWithCredentials(): null);},);}
}

这两个小部件都包装在一个 BlocBuilder 中,只有当肘位为它们各自的评估属性发出新的状态时,BlocBuilder 才负责重新构建这些小部件,因此,例如,如果用户没有在 email 字段中键入任何内容,EmailInputField 将永远不会被重新构建。

相反,如果所有字段都经过验证,按钮将调用 logInWithCredentials() 函数,该函数将根据 API 响应发出一个新状态(失败或成功)。

老铁记得 点赞、转发 ,我将更有动力呈现 Flutter 好文~~~~


© 猫哥

https://ducafecat.tech/

https://github.com/ducafecat

往期

开源

GetX Quick Start

https://github.com/ducafecat/getx_quick_start

新闻客户端

https://github.com/ducafecat/flutter_learn_news

strapi 手册译文

https://getstrapi.cn

微信讨论群 ducafecat

系列集合

译文

https://ducafecat.tech/categories/%E8%AF%91%E6%96%87/

Dart 编程语言基础

https://space.bilibili.com/404904528/channel/detail?cid=111585

Flutter 零基础入门

https://space.bilibili.com/404904528/channel/detail?cid=123470

Flutter 实战从零开始 新闻客户端

https://space.bilibili.com/404904528/channel/detail?cid=106755

Flutter 组件开发

https://space.bilibili.com/404904528/channel/detail?cid=144262

Flutter Bloc

https://space.bilibili.com/404904528/channel/detail?cid=177519

Flutter Getx4

https://space.bilibili.com/404904528/channel/detail?cid=177514

Docker Yapi

https://space.bilibili.com/404904528/channel/detail?cid=130578

Flutter BLoC 用户登录相关推荐

  1. flutter 一个用户登录页面

    一个用户登录页面 输入校验 import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart';void m ...

  2. flutter bloc 实例

    为了便于理解flutter bloc 我们先看看他是怎么用的 我们先定义相关的bloc test_bloc.dart import 'package:flutter_bloc/flutter_bloc ...

  3. 【探花交友DAY 02】项目搭建和用户登录功能的实现

    1. 项目介绍 探花交友是一个陌生人的在线交友平台,在该平台中可以搜索附近的人,查看好友动态,平台还会通过大数据计算进行智能推荐,通过智能推荐可以找到更加匹配的好友,这样才能增进用户对产品的喜爱度.探 ...

  4. java+flutter实现微信登录

    java+flutter实现微信登录 这篇文章很简单,讲的是微信登录,app端用flutter实现,服务端用java实现. app负责拿到微信用户的code,服务端通过code拿到openId. 一. ...

  5. 社交项目实战第一天(短信验证码实现用户登录)

    项目实战 <社交项目> 1.功能介绍 一乐交友是一个陌生人的在线交友平台,在该平台中可以搜索附近的人,查看好友动态,平台还会通过大数据计算进行智能推荐,通过智能推荐可以找到更加匹配的好友, ...

  6. TF1-项目搭建配置及用户登录

    TF1-项目搭建配置及用户登录 1.项目介绍 1.1.功能列表 1.2.项目背景 1.3.功能概述 1.3.1 用户登录 1.3.2.交友 首页 探花 搜附近 桃花传音 测灵魂 1.3.3.圈子 1. ...

  7. 【php增删改查实例】第十七节 - 用户登录(1)

    新建一个login文件,里面存放的就是用户登录的模块. <html><head><meta charset="utf-8"><style ...

  8. centos5.6 (64bit)编译安装vsftpd-2.3.4的配置(两种用户登录)[连载之电子商务系统架构]...

    centos5.6 (64bit)编译安装vsftpd-2.3.4的配置(两种用户登录) 出处:http://jimmyli.blog.51cto.com/我站在巨人肩膀上Jimmy Li 作者:Ji ...

  9. 基于jwt的用户登录认证

    最近在app的开发过程中,做了一个基于token的用户登录认证,使用vue+node+mongoDB进行的开发,前来总结一下. token认证流程: 1:用户输入用户名和密码,进行登录操作,发送登录信 ...

最新文章

  1. nodejs ld linux.so,请教大神,如何在独立虚拟主机上配置node.js开发环境?
  2. Lambda表达式入门,看这篇就够了!
  3. Java进一步增强AI支持:Java-AI库概述
  4. C++ 把输出结果写入到文件中
  5. 开发日记-20190704 关键词 读书笔记《Linux 系统管理技术手册(第二版)》DAY 10
  6. PHP删除文件unlink
  7. zkui:好用的zookeeper ui工具
  8. pixhawk软件架构
  9. 【成长点滴】对SMART原则的一些粗浅理解
  10. gradle引入依赖:_Gradle善良:获得更多的依赖性见解
  11. 如何使用jQuery将事件附加到动态HTML元素? [重复]
  12. java 对象equals_浅谈Java对象的equals方法
  13. swing怎么监听其他类的按钮_Swing舞出我人生 Vol.05 / 我想通过跳舞去寻找自己
  14. studio和solo哪个好_beats studio3 和solo3的区别再哪里?
  15. 影响力最大化 IC 蒙特卡洛模拟 贪心算法
  16. 某项目的双代号网络图如下所示_某工程项目的双代号网络计划如下图所示(时间单位:月)。...
  17. React Hook介绍(二):Effect Hook
  18. php vendor bin phinx,数据库Seeding
  19. node批量修改文件扩展名
  20. 深谈SCI论文写作技巧

热门文章

  1. 编程之美--3.5最短摘要的生成
  2. GaussDB数据类型介绍
  3. Ubuntu设置定时任务——每10秒钟执行一次命令(修改文件权限)
  4. 基于DNN的鼻咽癌鼻咽淋巴瘤数据处理
  5. Enumerating Trillion Triangles on Distributed Systems
  6. mysql中IGNORE使用
  7. 转行程序员日记---2020-10-19【开始加班了】
  8. C++ 捕获本机网卡的IP包并对其解析的实现
  9. 计算机又坏了,第二次回家
  10. 数据挖掘技术-使用函数进行简单的统计分析