flutter how to yield to a stream of bloc?

Viewed 740

Hi I'm new to flutter and dart. I'm following a lesson on internet which is practicing to use bloc to control states. First lesson is after showing appStart animation, turn to a login page.

the lesson was using 'mapEventToState':

class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState> {
    final UserRepository? _userRepository;

    AuthenticationBloc({UserRepository? userRepository})
    : assert(userRepository != null),
    _userRepository = userRepository, super(Uninitialized());
    @override
    Stream<AuthenticationState> mapEventToState(
        AuthenticationEvent event,
    ) async* {
        if (event is AppStarted) {
            yield* _mapAppStartedToState();
        } else if (event is LoggedIn) {
            yield* _mapLoggedInToState();
        } else if (event is LoggedOut) {
            yield* _mapLoggedOutToState();
        }
    Stream<AuthenticationState> _mapAppStartedToState() async* {
        log('_mapAppStartedToState is running.');
        try {
            final bool? isSigned = await _userRepository?.isSignedIn();
            if (isSigned != null) {
                if (isSigned) {
                    final String? name = await _userRepository?.getUser();
                    yield Authenticated(name);
                }
                else {
                    yield Unauthenticated();
                }
            }
        } catch (_) {
            yield Unauthenticated();
        }
    }

    Stream<AuthenticationState> _mapLoggedInToState() async* {
        log('_mapLoggedInToState is running.');
        yield Authenticated(await _userRepository?.getUser());
    }

    Stream<AuthenticationState> _mapLoggedOutToState() async* {
        log('_mapLoggedOutToState is running.');
        yield Unauthenticated();
        _userRepository?.signOut();
    }
}

turns out 'mapEventToState' was removed. According to this page(https://github.com/felangel/bloc/issues/2526), I try to use on< event > instead:

@override
AuthenticationBloc({UserRepository? userRepository})
: assert(userRepository != null, 'userRepository == null'),
    _userRepository = userRepository,
    super(Uninitialized()) {
        log('AuthenticationBloc is running.');
        on<AppStarted>(_appStarted);
        on<LoggedIn>(_loggedIn);
        on<LoggedOut>(_loggedOut);
    }
Stream<AuthenticationState> _appStarted(AuthenticationEvent event, Emitter<AuthenticationState> emit) async* {
    log('_appStarted is running.');
    yield* _mapAppStartedToState();
}

But it didn't work. Even log('_appStarted is running.'); didn't show at console.

I tried to change type and aync*. It would show console log if _appStarted isn't aync.

void _appStarted(AuthenticationEvent event, Emitter<AuthenticationState> emit) {
    log('_appStarted is running.');
    // yield* _mapAppStartedToState();
}

However, it can't yield to stream as _appStarted isn't aync. Makes me confused.

Please let me know if I got some misunderstand about bloc and stream. Happy to see any solution or advise.

1 Answers

You no longer need your one function per event, because you already have it:

void _appStarted(AuthenticationEvent event, Emitter<AuthenticationState> emit) {
    log('_appStarted is running.');
     try {
            final bool? isSigned = await _userRepository?.isSignedIn();
            if (isSigned != null) {
                if (isSigned) {
                    final String? name = await _userRepository?.getUser();
                    emit(Authenticated(name));
                }
                else {
                    emit(Unauthenticated());
                }
            }
        } catch (_) {
            emit(Unauthenticated());
        }
}

If you want to delegate this to another function, just remove the stream return value and pass the emitter.

Related