Search code examples
flutterstatebloc

BlocListener not detecting state when widget not in view


I have a timer widget with a bloclistener attached to it. When timer completes, an event is emitted and in turn a TimerCompleted state is emitted which is used to reset the timer and keep track of number of completed timers within a bloclistener.

This works well, until I navigate to another page while the timer is running.

The expected behavior is on timer running out while I am on another page, the timer resets and number of completed timers is incremented.

However, when I navigate back to page, i find the timer just counts down to zero and all the actions that are supposed to be triggered when the bloclistener gets the TimerCompletedState do not occur.

I have used print statements(My bad for not learning how to debug) and the TimerComplete state emits from the bloc handler. It's the block listener that doesn't hear the state when the widget is not in view(when I have navigated to another page)

I have tried to move my executed instructions within the bloclistener to the BLoc handler but I am using AppLifeCycle methods that need a widget to function (as far as I know). I also require to read values from other blocs which require the context variable that I can't pass since my emitted state is due to code in the bloc handler and not an event added by a widget with context.

State-emitting code within the timerBloc:

      on<TimerTicked>(TimerTicked event, Emitter<TimerState> emit) {
        if (event.duration > 0) {
          emit(TimerInProgressState(event.duration));
        } else {
          emit(TimerCompleteState());
        }
      }

BlocListener in my Timer widget:

    Widget build(BuildContext context) {
        return BlocListener<TimerBloc, TimerState>(
          listener: (context, state) {
          
            if (state is TimerCompleteState) {
            //Reset timer
            BlocProvider.of<TimerBloc>(context)
                    .add(InitializeTimerEvent(duration: 25));
            //Increment completed timers
            BlocProvider.of<TimerBloc>(context).add(SessionTrackingEvent(
                  sessionCount: sessionCount++,
                ));
            }

In summary, bloclistener doesnt hear state when widget not in view

My question is, is BlocListener not designed to work when a widget is not in view? If so, what's an alternative approach in that scenario and if not, what could I be doing wrong?


Solution

  • It turns out, the listener was nested too deep down the tree to be effective when I navigated to another page, since I am using BottomNavigationBar. After Placing the listener above the BottomNavigationBar widget, the listener is now capturing the state changes regardless of what tab I am currently in.