0

With a state change observer I can see that my bloc changes its states to LoadInProgress and back to PmLoadSuccess. However, the widget is not called with the change to LoadInProgress. I have a breakpoint in the BlocBuilder, however, the code stops there only when PmLoadSuccess is emitted.

My state definition

@freezed
class ProblemManagerState with _$ProblemManagerState {
  const factory ProblemManagerState.initial() = PmInitial;
  const factory ProblemManagerState.loadInProgress() = PmLoadInProgress;
  const factory ProblemManagerState.loadSuccess(
      Problem problem) = PmLoadSuccess;
      ) = PmSyncFailed;
}

The bloc

@injectable
class ProblemManagerBloc extends Bloc<ProblemManagerEvent, ProblemManagerState> {
  final IProblemsRepository problemsRepository;
  ProblemManagerBloc(this.problemsRepository) : super(PmInitial());

  @override
  Stream<ProblemManagerState> mapEventToState(
    ProblemManagerEvent event,
  ) async* {
    yield PmLoadInProgress();  // <<< does not emit to widget 
    yield* event.map(
      pmProblemRequested: (e) async* {
        yield ProblemManagerState.loadInProgress();  // <<< doesn't emit either 
        print (state);
        yield* _mapPmProblemRequestedToState(e);
      },
    );
  }

  Stream<ProblemManagerState> _mapPmProblemRequestedToState(/*PmProblemRequested*/dynamic event) async* {
    dynamic nextProblem;
    late int problemClassId;
    problemClassId = event.problemClassId!;
    }
    final String rootId = await _getNextProblemRootId(problemClassId);
    final Either<StorageFailure, Problem> failureOrProblem = await problemsRepository.getProblem(rootId);
    yield failureOrProblem.fold(
            (fail) => PmLoadFailure(fail),
            (load) => PmLoadSuccess(load)); // <<< yield does emit to  widget
  }

The widget (calling another widget if load successful)

class ProblemManagerPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<ProblemManagerBloc, ProblemManagerState>(
        builder: (context, state) {
          return state.map(  // <<< breakpoint not reached with PmLoadInProgress (=ProblemManagerState.loadInProgress)
              initial: (_) => Container(),
              loadInProgress: (_) => const Center(
                  child: CircularProgressIndicator(),
              ),
              loadSuccess: (state) => PmGateway(state.problem),
          );
        }
    );
  }
}
w461
  • 2,168
  • 4
  • 14
  • 40
  • Have you seen this? https://stackoverflow.com/questions/55503807/flutter-bloc-blocbuilder-not-getting-called-after-an-update-listview-still-dis – RaSha Aug 20 '21 at 16:32
  • yes, but that is about Equatable. I am using freezed instead and there is no overriding the props (I know of). I have followed the DDD tutorial of Reso Coder https://github.com/ResoCoder/finished-flutter-firebase-ddd-course/blob/master/lib/application/notes/note_watcher/note_watcher_bloc.dart – w461 Aug 20 '21 at 16:41
  • I have changed this from freezed to Equatable. No change... Could this be caused because the BlocBuilder of this bloc does not directly render anything and because the Widget called by the Widget `PmGateway` (seen in the snippet above) has its own bloc which does not emit a new state? I was expecting that if the root bloc emits a new state that does not rebuild the child widget with its bloc, the child widget vanishes. – w461 Aug 20 '21 at 18:21

1 Answers1

0

Taken from github issue list

This is expected because BlocBuilder can only rebuild at 60fps. In this case you are emitting states faster than BlocBuilder can rebuild.

w461
  • 2,168
  • 4
  • 14
  • 40