1 year ago

#386839

test-img

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

Accepted video resources