1 year ago
#386839
Yusof Antar
Flutter Bloc Not updating immediately, only after a refresh or rebuild
I am working on a flutter project, so I was trying to use Flutter bloc state management. I built everything from state to event and also the bloc thing. like the code below:
State:
abstract class UserState extends Equatable {
const UserState();
@override
List<Object> get props => [];
}
class UserInitialState extends UserState {}
class UserLoadingState extends UserState {
@override
List<Object> get props => [];
}
class UserLoadedState extends UserState {
final UserModel user;
const UserLoadedState(this.user);
@override
List<Object> get props => [user];
}
class UserValidationState extends UserState {
final Map<String, dynamic> validation;
const UserValidationState(this.validation);
@override
List<Object> get props => [validation];
}
class UserErrorState extends UserState {
final Map<String, dynamic> error;
const UserErrorState(this.error);
@override
List<Object> get props => [error];
}
Event:
class LoginUserEvent extends UserEvent {
final String email, password;
const LoginUserEvent({this.email, this.password});
@override
List<Object> get props => [];
}
Bloc:
UserBloc(this._userReprository) : super(UserInitialState()) {
on<LoginUserEvent>((event, emit) async {
emit(UserLoadingState());
try {
await _userReprository
.loginUser(
email: event.email,
password: event.password,
)
.then((result) {
if (result.contains('success')) {
emit(UserLoadedState(result[1]));
} else if (result.contains('errors')) {
emit(UserValidationState(result[1]));
}
});
} catch (e) {
emit(UserErrorState(e));
}
});
}
so it should work like when I click on the button it switch to loading event then after response it either load or throw a validation error or it catch an error if something happened. well unfortunately the UI is not updating immedtialy, only after a second refresh or a setstate of another way or something that rebuild it it only change Here is the code of the UI:
@override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
// Clearing all TextEdititng Controller Values
_clearValues() {
_email.clear();
_password.clear();
_valErrors.clear();
}
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Container(
margin: EdgeInsets.only(top: deviceSize.height * 0.05),
child: Column(
children: [
Container(
margin: const EdgeInsets.symmetric(vertical: 20),
child: Material(
shadowColor: Colors.black54,
color: Theme.of(context).colorScheme.primary,
elevation: 2,
borderRadius: BorderRadius.circular(35),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10,
horizontal: 15,
),
child: SvgPicture.asset(
'./assets/img/auth_logo.svg',
width: deviceSize.width * 0.5,
height: deviceSize.width * 0.5,
),
),
),
),
const SizedBox(
height: 10,
),
Column(
children: <Widget>[
Container(
margin: const EdgeInsets.symmetric(horizontal: 20),
child: Material(
borderRadius: BorderRadius.circular(25),
elevation: 2,
shadowColor: Colors.black54,
child: TextField(
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
controller: _email,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.email),
border: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.white, width: 32.0),
borderRadius: BorderRadius.circular(25.0),
),
labelText: 'Email',
),
),
),
),
_valErrors.containsKey('email')
? Column(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30,
vertical: 1,
),
child: Text(
_valErrors['email'],
textAlign: TextAlign.start,
style: const TextStyle(
color: Colors.red,
),
),
),
),
const SizedBox(
height: 15,
)
],
)
: const SizedBox(
height: 25,
),
],
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 20),
child: Material(
elevation: 2,
shadowColor: Colors.black54,
borderRadius: BorderRadius.circular(25),
child: TextField(
textInputAction: TextInputAction.done,
obscureText: hiddenContent,
controller: _password,
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.lock),
suffixIcon: IconButton(
icon: hiddenContent
? const Icon(Icons.visibility)
: const Icon(Icons.visibility_off),
onPressed: () {
setState(() {
hiddenContent = !hiddenContent;
});
}),
border: OutlineInputBorder(
borderSide:
const BorderSide(color: Colors.white, width: 32.0),
borderRadius: BorderRadius.circular(25.0),
),
labelText: 'Password',
),
),
),
),
_valErrors.containsKey('password')
? Column(
children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30, vertical: 1),
child: Text(
_valErrors['password'],
textAlign: TextAlign.start,
style: const TextStyle(
color: Colors.red,
),
),
),
),
const SizedBox(
height: 15,
)
],
)
: const SizedBox(
height: 25,
),
BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
if (state is UserLoadingState) {
return const CircularProgressIndicator();
}
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Material(
elevation: 2,
shadowColor: Colors.black54,
borderRadius: BorderRadius.circular(25),
child: TextButton(
style: ButtonStyle(
padding: MaterialStateProperty.all<EdgeInsets>(
const EdgeInsets.symmetric(
vertical: 15,
horizontal: 30,
),
),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
),
backgroundColor: MaterialStateProperty.all<Color>(
Theme.of(context).colorScheme.primary,
),
),
onPressed: () async {
// If Statement to make sure THe validation is correct and to show Messages
setState(() {
if (_email.text.isEmpty) {
_valErrors['email'] = 'This Field is Required';
} else {
_valErrors.remove('email');
}
if (_password.text.isEmpty) {
_valErrors['password'] =
'This Field is Required';
} else if (_password.text.length < 8) {
_valErrors['password'] =
'Password must be Greater Than 8';
} else {
_valErrors.remove('password');
}
});
// Databse Function Login
if (_valErrors.isEmpty) {
context.read<UserBloc>().add(
LoginUserEvent(
email: _email.text,
password: _password.text,
),
);
if (state is UserLoadedState) {
_clearValues();
Navigator.of(context)
.pushReplacementNamed('/botnavbar');
} else if (state is UserValidationState) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text(
'There is some problems'),
content: Text(state
.validation['message']
.toString()),
actions: <Widget>[
TextButton(
onPressed: () =>
Navigator.of(context).pop(),
child: const Text('Okay'),
),
],
);
});
}
}
},
child: const Text(
'Login',
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
),
),
),
Material(
elevation: 2,
shadowColor: Colors.black54,
borderRadius: BorderRadius.circular(25),
child: TextButton(
style: ButtonStyle(
padding: MaterialStateProperty.all<EdgeInsets>(
const EdgeInsets.symmetric(
vertical: 15,
horizontal: 35,
),
),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
side: BorderSide(
color: Theme.of(context).colorScheme.primary,
),
),
),
),
onPressed: () {
Navigator.of(context)
.pushReplacementNamed('/register');
},
child: Text(
'Register',
style: TextStyle(
fontSize: 20,
color: Theme.of(context).colorScheme.primary,
),
),
),
),
],
);
},
),
],
),
),
),
);
}
I tried to use the blocbuilder on the whole scaffold but still the same problem Hope you can help me guys
flutter
state
0 Answers
Your Answer