Bloc Dart : When I add async* to my on<Event> function in my_bloc_bloc.dart file , add an event with flutter_bloc does not make anything

Issue

Here is my code when I add async* (Hello World! is not printed):

import 'package:alltoo_mobile/authenticate/bloc/authenticate_bloc.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';

part 'login_event.dart';
part 'login_state.dart';

class LoginBloc extends Bloc<LoginEvent, LoginState> {
  AuthenticateBloc _authenticateBloc;
  LoginBloc(this._authenticateBloc) : super(LoginInitial()) {
    on<LoginEvent>((event, emit) async* {
      print("Hello World!");
      // if (event is LoginButtonPressed) yield * _mapLoginButtonPressed(event);
    });
  }
  Stream<LoginState> _mapLoginButtonPressed(LoginButtonPressed event) async* {
    yield LoginInitial();
  }
} 

Here is my code when Hello World! is printed (I just removed async*):

import 'package:alltoo_mobile/authenticate/bloc/authenticate_bloc.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';

part 'login_event.dart';
part 'login_state.dart';

class LoginBloc extends Bloc<LoginEvent, LoginState> {
  AuthenticateBloc _authenticateBloc;
  LoginBloc(this._authenticateBloc) : super(LoginInitial()) {
    on<LoginEvent>((event, emit){
      print("Hello World!");
      // if (event is LoginButtonPressed) yield * _mapLoginButtonPressed(event);
    });
  }
  Stream<LoginState> _mapLoginButtonPressed(LoginButtonPressed event) async* {
    yield LoginInitial();
  }
} 

Where I add the event in my login.dart file (this Inkwell is in Material widget) :

InkWell(
  onTap: () {
    if (_formKey.currentState!.validate()) {
      BlocProvider.of<LoginBloc>(context).add(
          LoginButtonPressed(
              username: _usernameController.text,
              password: _passwordController.text));
    }
  },
  borderRadius: BorderRadius.circular(14.0),
  child: Center(
    child: Text(
      'Login',
      style: heading5.copyWith(color: Colors.white),
    ),
  ),
),

Where I create my bloc in my main.dart file :

BlocBuilder<AuthenticateBloc, AuthenticateState>(
  builder: (context, state) {
    if (state is AuthenticateLogged) return Calendar();
    return BlocProvider<LoginBloc>(
      create: (context) =>
          LoginBloc(BlocProvider.of<AuthenticateBloc>(context)),
      child: LoginPage(),
    );
  },
),

Solution

It is not possible for a bloc event to have a return type of Stream<state>, that is a thing from the old version of bloc, now all events must return Future<void> or void, which means that your event get’s ignored if you add the async* keyword, and I believe that is why hello world does not print.

This is the way to do what you probably want to do:

LoginBloc(this._authenticateBloc) : super(LoginInitial()) {
    on<LoginButtonPressed>((event, emit){      
      print('hello world');
      emit(_mapLoginButtonPressed(event));
    });
  }
   LoginState _mapLoginButtonPressed(LoginButtonPressed event) {
    return LoginInitial();
  }
} 

you can make events async, but not async* not sync*, and you should use the emitter to emit the new value, instead of yielding it.

Answered By – h8moss

Answer Checked By – Gilberto Lyons (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *