Home > Blockchain >  Flutter BlocListener not listening to state changes even this after emitting different states
Flutter BlocListener not listening to state changes even this after emitting different states

Time:10-14

I have a bloc that emits some states User states

These are my states at the moment

part of 'user_bloc.dart';

@immutable
abstract class UserState extends Equatable {}

class UserInitial extends UserState {
  @override
  List<Object?> get props => [];
}

class UserCreating extends UserState {
  @override
  List<Object?> get props => [];
}

class UserCreated extends UserState {
  late final String message;
  UserCreated(this.message);
  @override
  List<Object?> get props => [];
}

class UserError extends UserState {
  late final String error;
  UserError(this.error);
  @override
  List<Object?> get props => [error];
}

Below Is also my events for the UserBloc

part of 'user_bloc.dart';

@immutable
abstract class UserEvent extends Equatable {
  @override
  List<Object?> get props => [];
}

class CreateUser extends UserEvent {
  final String name;
  final String email;
  final String password;
  final String? imageUrl;

  CreateUser({
    required this.name,
    required this.email,
    required this.password,
    required this.imageUrl,
  });
}

And below is my main UserBloc where I am emitting states

class UserBloc extends Bloc<UserEvent, UserState> {
  UserRepository userRepository;
  UserBloc(this.userRepository) : super(UserInitial()) {
    on<CreateUser>((event, emit) async {
      emit(UserCreating());
      try {
        final result = await userRepository.signup(
          name: event.name,
          password: event.password,
          email: event.email,
        );
        print(result);
        emit(
          UserCreated('User created successfully'),
        );
      } on DioError catch (error) {
        emit(
          UserError(
            error.response.toString(),
          ),
        );
      } catch (error) {
        emit(
          UserError(
            error.toString(),
          ),
        );
      }
    });
  }
}

I have wrapped my MaterialApp with both Multirepository provider and muiltiblocprovider where I have all my blocs being initialised. Below is the code for that.

@override
  Widget build(BuildContext context) {
    return MultiRepositoryProvider(
      providers: [
        RepositoryProvider(create: (context) => UserRepository()),
      ],
      child: MultiBlocProvider(
        providers: [
          BlocProvider<ThemeModeCubit>(
            create: (context) => ThemeModeCubit(),
          ),
          BlocProvider<InternetCubit>(
            create: (context) => InternetCubit(connectivity),
          ),
          BlocProvider(
            create: (context) => UserBloc(
              RepositoryProvider.of<UserRepository>(context),
            ),
          )
        ],
        child: ValueListenableBuilder(...)

And finally, I am using bloc listener inside my code to listen to changes in the bloc but I don't get any response prior to the change.

final userRepo = RepositoryProvider.of<UserRepository>(context);

child: BlocListener(
            bloc: UserBloc(userRepo),
            listener: (ctx, state) {
              print('listener called');
              if (state is UserCreating) {
                print('loading emited');
                QuickAlert.show(
                  context: context,
                  type: QuickAlertType.loading,
                  title: 'Loading',
                  text: 'Signing up',
                );
              } else if (state is UserCreated) {
                QuickAlert.show(
                  context: context,
                  type: QuickAlertType.success,
                  text: 'User created sucessfully', //state.message,
                );
              } else if (state is UserError) {
                QuickAlert.show(
                  context: context,
                  type: QuickAlertType.success,
                  text: state.error,
                );
              }
            },
            child: Form(...)

This is how I am calling my event from the user

context.read<UserBloc>().add(
        CreateUser(
          name: name,
          email: email,
          password: password,
          imageUrl: imageUrl,
      ),
   );

CodePudding user response:

I see you had provide a UserBloc in MultiBlocProvider outside:

BlocProvider(
    create: (context) => UserBloc(
       RepositoryProvider.of<UserRepository>(context),
    ),
)

then you shouldn't pass another new UserBloc to BlocBuilder, that will make BlocBuilder listen to different UserBloc instance, change

BlocListener(
   bloc: UserBloc(userRepo),
   listener: (ctx, state) {
}

to

BlocListener<UserBloc, UserState>(
    listener: (ctx, state) {
}

CodePudding user response:

If the widget is not updated it's because bloc considers the emitted state to be the same as the the previous one.

I see the you extend equatable.

Equatable overrides the == operator for you, and uses props to check for equality. Both UserCreating and UserCreated return an empty list, so probably Bloc doesn't see any change.

I would personally override the == operator to aslo check for the object types. In case you want to keep using equatable, just make sure that the returned props actually differ.

  • Related