The original
Medium.com/theotherdev…
preface
First, since this is not a basic tutorial, we take it for granted that this is a roadmap, and we also include a little validation and Formoz packages to create reusable models. This is not the purpose of this tutorial to show how this will work, as you will see in the next tutorial. For the login section, we also used a subset of BLoC (Cubit) for tutorial purposes, so you’ll see the difference between the two.
Code, you can read the code first, then look at the documentation
Github.com/Alessandro-…
reference
- Pub. Flutter – IO. Cn/packages/eq…
- Pub. Flutter – IO. Cn/packages/va…
- Pub. Flutter – IO. Cn/packages/fl…
- Pub. Flutter – IO. Cn/packages/fo…
The body of the
start
Before we begin, let’s add some necessary packages in pubspec.yaml:
Equatable: ^2.0.0 flutter_bloc: ^7.0.0 formz: ^0.3.2Copy the code
Adding the Equatable package will only make your job easier, but if you want to compare instances of classes manually, just override “==” and hashCode.
The login status
Let’s start with a class that contains form state and all field states:
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;
@override
List<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, ); }}Copy the code
Now let’s create our LoginCubit, which will take care of executing the logic, such as retrieving email and printing new status via 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())); }}}Copy the code
But how do we connect wrist ruler to our user interface? Here’s a relief for BlocProvider, a widget that provides a block for its children using blocProvider.of
(context)
BlocProvider(
create: (_) => LoginCubit(),
child: LoginForm(),
),
Copy the code
Login form
Now that it seems to be all in its own place, it’s time to tackle our final piece of puzzle, the entire user interface
class LoginForm extends StatelessWidget {
const LoginForm({Key key}) : super(key: key);
@override
Widget 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(), ], ) ); }}Copy the code
To react to the new state emitted by Cubit, we need to wrap our form in a BlocConsumer, and now we’ll expose a listener and a builder.
- Listener
Here we will listen for state changes, such as displaying errors or performing navigation in response to API calls.
- Builder
Here we will display the UI response state changes to our Cubit.
The user interface
Our user interface consists of a column and five child elements, but we only show two short widgets:
class _EmailInputField extends StatelessWidget {
@override
Widget build(BuildContext context) {
returnBlocBuilder<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);
@override
Widget build(BuildContext context) {
returnBlocBuilder<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); }); }}Copy the code
Both widgets are wrapped in a BlocBuilder that takes care of rebuilding the widgets only when the cubit emits a new state for their respective evaluation properties, so if the user doesn’t type anything into the email field, for example, The EmailInputField will never be rebuilt.
Instead, if all fields are validated, the button calls the logInWithCredentials() function, which issues a new state (failed or succeeded) based on the API response.
Old tie remember to like and forward, I will be more motivated to present Flutter good article ~~~~
The elder brother of the © cat
ducafecat.tech/
github.com/ducafecat
The issue of
Open source
GetX Quick Start
Github.com/ducafecat/g…
News client
Github.com/ducafecat/f…
Strapi manual translation
getstrapi.cn
Wechat discussion group Ducafecat
A series of collections
The translation
Ducafecat. Tech/categories /…
Dart programming language basics
Space.bilibili.com/404904528/c…
Start Flutter with zero basics
Space.bilibili.com/404904528/c…
Flutter combat news client from scratch
Space.bilibili.com/404904528/c…
Flutter component development
Space.bilibili.com/404904528/c…
Flutter Bloc
Space.bilibili.com/404904528/c…
Flutter Getx4
Space.bilibili.com/404904528/c…
Docker Yapi
Space.bilibili.com/404904528/c…