Я застрял на этом с утра, я работаю с блоком, у меня есть событие, состояние и блок, и я хочу обновить значение некоторых значений в зависимости от ответа, полученного от сервера. У меня есть переменная, которую я назвал showPassword в своем состоянии, и я инициализировал ее как false. Теперь, после того как проверка электронной почты возвращает ответ 200, я хочу обновить showPassword до значения true, а затем обновить свой пользовательский интерфейс. Проблема здесь в том, что даже когда сервер возвращает ответ 200, showPassword все равно не обновляется. Это то, что я сделал
class LoginState {
final String email;
final String password;
final bool showEmail;
final bool showPassword;
LoginState({
this.email = "",
this.password = "",
this.showEmail = false,
this.showPassword = false,
});
LoginState copyWith({
String? email,
String? password,
bool? showEmail,
bool? showPassword,
}) {
return LoginState(
email: email ?? this.email,
password: password ?? this.password,
showEmail: showEmail ?? this.showEmail,
showPassword: showPassword ?? this.showPassword,
);
}
}
class LoginBloc extends Bloc<LoginEvents, LoginState> {
LoginBloc() : super(LoginState()) {
on<LoginEmailEvent>(_emailEvent);
on<LoginPasswordEvent>(_passwordEvent);
}
void _emailEvent(LoginEmailEvent event, Emitter<LoginState> emit) {
emit(state.copyWith(email: event.email));
}
void _passwordEvent(LoginPasswordEvent event, Emitter<LoginState> emit) {
emit(state.copyWith(password: event.password));
}
}
//Method in the controller that performed the email verification
Future<void> handlePreview() async {
final state = context.read<AuthBloc>().state;
final loginState = context.read<LoginBloc>().state;
String email = state.email;
if (email.isEmpty) {
toastInfo(msg: "Please Enter Email Address");
return;
}
try {
AuthModel authModel = AuthModel();
authModel.email = email;
AuthRepository.preview(authModel).then((value) => {
if (value.response!.code == 200)
{
//This is where I changed the value from false to true
// But still not updating
loginState.copyWith(showPassword: true)
//show login fields
}
else
{
loginState.copyWith(showPassword: false),
toastInfo(msg: value.response!.message!)
//show sign up fields
}
});
} catch (e) {
toastInfo(msg: e.toString());
}
//this printing returns false even when the response was 200
print(loginState.copyWith().showPassword);
}
@override
Widget build(BuildContext context) {
AuthController authController = AuthController(context: context);
return BlocBuilder<LoginBloc, LoginState>(builder: (context, state) {
return Scaffold(
backgroundColor: Color(0xFFF1F3F6),
body: SafeArea(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 100),
//horizontal: ScreenUtil().setWidth(120)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const SizedBox(
height: 50,
),
Center(
child: Visibility(
visible: state.showPassword,
child: const Text(
"Login",
style: TextStyle(
color: Color(0xFF4D70A6),
fontSize: 26,
fontWeight: FontWeight.bold),
),
),
),
const SizedBox(
height: 40,
),
Stack(
children: <Widget>[
buildTextField("Email", "", (value) {
context.read<LoginBloc>().add(LoginEmailEvent(value));
context.read<AuthBloc>().add(UserAuthEvent(value));
}),
// Center(
// child: CircularProgressIndicator(),
// )
],
),
SizedBox(
height: 5,
),
Visibility(
visible: state.showEmail,
child: buildLoadingIndicator()),
GestureDetector(
onTap: () async {
authController.handlePreview();
},
child: Container(
child: const Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Center(
child: Icon(
Icons.verified,
size: 20,
color: Colors.grey,
),
),
],
),
),
),
Visibility(
visible: state.showPassword,
child: buildTextField("Password", "password", (value) {
context
.read<LoginBloc>()
.add(LoginPasswordEvent(value));
print(value);
}),
),
const SizedBox(
height: 50,
),
Visibility(
visible: state.showPassword,
child: GestureDetector(
onTap: () {
AuthController(context: context).handleLogin();
},
child: Container(
width: double.infinity,
alignment: Alignment.center,
height: 50,
margin: EdgeInsets.symmetric(vertical: 15),
decoration: BoxDecoration(
color: Color(0xFFF1F3F6),
borderRadius:
BorderRadius.all(Radius.circular(10)),
boxShadow: [
BoxShadow(
offset: Offset(10, 10),
color: Color(0xFF4D70A6).withOpacity(0.2),
blurRadius: 16),
const BoxShadow(
offset: Offset(-10, -10),
color: Color.fromARGB(170, 255, 255, 255),
blurRadius: 10),
]),
child: const Text(
"Login",
style: TextStyle(
color: Color(0xFF4D70A6), fontSize: 16),
),
),
),
),
],
)),
));
});
}
Когда вы используете метод copyWith
, вы создаете новый экземпляр LoginState
, но этот новый экземпляр не передается обратно в пользовательский интерфейс. Чтобы обновить пользовательский интерфейс, вам нужно использовать функцию излучения внутри обработчика событий вашего блока.
Добавьте новое событие в свой login_event.dart
файл
class EmailVerificationResultEvent extends LoginEvent {
final bool isSuccess;
EmailVerificationResultEvent(this.isSuccess);
}
Затем обработайте это событие в своем файле login_bloc.dart
.
void _emailVerificationResult(EmailVerificationResultEvent event, Emitter<LoginState> emit) {
emit(state.copyWith(showPassword: event.isSuccess));
}
И отправьте EmailVerificationResultEvent
, когда получите ответ от серверной части.
if (value.response!.code == 200) {
context.read<LoginBloc>().add(EmailVerificationResultEvent(true));
} else {
context.read<LoginBloc>().add(EmailVerificationResultEvent(false));
}