Search code examples
fluttermigrationblocstate-managementflutter-bloc

Migrating to a newer BloC version problem


I'm trying to learn about the BloC pattern, I first meet this patter in the following git repository fitness, I tried using my own code but it had many errors and problems, so I figured I'd better try 1 to 1 their code first and then Ill see changes, so I tried it but their code also results in errors.

I solved some of them, but the BloC related one are still there, you can refer to this issue I opened for them PageSwipe/Change Issue where I explain the errors and where they originated from in the code.

I've tried to follow the migration guide located here migration guide, but with no luck so far.

The BloC code can be found here first page BloC code

if there is anything else related that needed in order to solve this problem, comment it and I'll add it

Error:

Bad state: add(PageSwipedEvent) was called without a registered event handler.
Make sure to register a handler via on<PageSwipedEvent>((event, emit) {...})

Line in code that result in that error:

bloc.add(PageChangedEvent());
// or
bloc.add(PageSwipedEvent(index: index));

BloC code:

import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';

part 'onboarding_event.dart';
part 'onboarding_state.dart';

class OnboardingBloc extends Bloc<OnboardingEvent, OnboardingState> {
  OnboardingBloc() : super(OnboardingInitial());

  int pageIndex = 0;

  final pageController = PageController(initialPage: 0);

  @override
  Stream<OnboardingState> mapEventToState(
    OnboardingEvent event,
  ) async* {
    if (event is PageChangedEvent) {
      if (pageIndex == 2) {
        yield NextScreenState();
        return;
      }
      pageIndex += 1;

      pageController.animateToPage(
        pageIndex,
        duration: Duration(milliseconds: 500),
        curve: Curves.ease,
      );

      yield PageChangedState(counter: pageIndex);
    } else if (event is PageSwipedEvent) {
      pageIndex = event.index;
      yield PageChangedState(counter: pageIndex);
    }
  }
}

I tried adding this also:

on<PageSwipedEvent>((event, emit) => mapEventToState(event));

but it doesnt seem to work (it doesn't show the problem anymore, but it does not get the job done either.

Edit:

Flutter version:

Flutter version


Solution

  • You are on the right track with on<PageSwipedEvent>((event, emit) => mapEventToState(event));. The problem is that you are mixing several different versions of BLoC in one piece of code. The mapEventToState() method uses yield instead of on<Event>((event, emit) => emit(State)). This was changed in BLoC 8.0.0. https://pub.dev/packages/flutter_bloc/changelog. Since you said that adding on<PageChangedEvent>((event, emit) => mapEventToState(event)); fixed the error even though the code still doesn't produce a result, I think you are using version 8.0.0 or higher.

    Try switching the yield to on<Event>((event, emit) => emit(State)) and moving the on handlers inside the constructor:

    class OnboardingBloc extends Bloc<OnboardingEvent, OnboardingState> {
    
      int pageIndex = 0;
      final pageController = PageController(initialPage: 0);
    
      OnboardingBloc() : super(OnboardingInitial()){
    
        on<PageChangedEvent>((event, emit) async {
        
            if (pageIndex == 2) {
                emit(NextScreenState());
                return;
              }
              pageIndex += 1;
            
              pageController.animateToPage(
                pageIndex,
                duration: Duration(milliseconds: 500),
                curve: Curves.ease,
              );
            emit(PageChangedState(counter: pageIndex));
        
        });
    
        on<PageSwipedEvent>((event, emit) async {
           pageIndex = event.index;
           emit(PageChangedState(counter: pageIndex));
        });
    
    }