anber
anber

Reputation: 3665

Flutter BLoC: listener does not work after emit

Brief summary: I see in debug that emit(DataLoadedState(result)); is called but listener does not work:

      listener: (context, state) {
        if (state is DataLoadedState) {
          savedSearches = state.savedSearches;
        }
      },

Details:

I have stateful widget. On initState I add LoadSavedSearchesEvent and Listener works ok:

  listener: (context, state) {
    if (state is DataLoadedState) {
      savedSearches = state.savedSearches;
    }
  },

But when app is runnung and state ShowLandingState happens I add the same event to the same bloc:

    if (state is ShowLandingState) {
      widget.bloc.add(LoadSavedSearchesEvent());
    }

I see in debug that bloc works and emit(DataLoadedState(result)); fired, but this listened does not work:

  listener: (context, state) {
    if (state is DataLoadedState) {
      savedSearches = state.savedSearches;
    }
  },

I know that Listener will not listen if the same State is emitted twice in a row, but I did not override hashCode or equals in DataLoadedState class so it should be different states from the bloc perspective.

class SavedSearchWidget extends StatefulWidget {
  final SavedSearchesBloc bloc;
  final SearchScreenBloc searchScreenBloc;

  const SavedSearchWidget({
    super.key,
    required this.bloc,
    required this.searchScreenBloc,
  });

  @override
  State<SavedSearchWidget> createState() => _SavedSearchWidgetState();
}

class _SavedSearchWidgetState extends State<SavedSearchWidget> {
  List<SavedSearchPresentation>? savedSearches;

  @override
  void initState() {
    widget.bloc.add(LoadSavedSearchesEvent());
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MultiBlocListener(
      listeners: [
        BlocListener(
          bloc: widget.searchScreenBloc,
          listener: (context, state) {
            if (state is ShowLandingState) {
              widget.bloc.add(LoadSavedSearchesEvent());
            }
          },
        ),
        BlocListener(
          bloc: widget.bloc,
          listener: (context, state) {
            if (state is DataLoadedState) {
              savedSearches = state.savedSearches;
            }
          },
        ),
      ],
      child: BlocBuilder(
        bloc: widget.bloc,
        builder: (context, state) {
          // draw UI
        },
      ),
    );
  }
}

Bloc code:

abstract class SavedSearchesState {}

class InitState extends SavedSearchesState {}

class DataLoadedState extends SavedSearchesState {
  SavedSearchesResponse savedSearches;

  DataLoadedState(this.savedSearches);
}

class SavedSearchesBloc extends Bloc<SavedSearchesEvent, SavedSearchesState> {
  final ISavedSearchRepository _repository;

  SavedSearchesBloc(this._repository) : super(InitState()) {
    on<LoadSavedSearchesEvent>(onLoadSavedSearchesEvent);
  }

  Future<void> onLoadSavedSearchesEvent(
    LoadSavedSearchesEvent event,
    Emitter<SavedSearchesState> emit,
  ) async {
    final result = await _repository.loadAll();
    emit(DataLoadedState(result));
  }
}

Upvotes: 0

Views: 597

Answers (1)

Akash Bisht
Akash Bisht

Reputation: 163

Try something like this :

 Future<void> onLoadSavedSearchesEvent(
    LoadSavedSearchesEvent event,
    Emitter<SavedSearchesState> emit,
  ) async {
    /// Emit a different state before emitting the DataLoadedState
    emit(InitState());
    final result = await _repository.loadAll();
    emit(DataLoadedState(result));
  }

Upvotes: 0

Related Questions