Search code examples
dartbloc

Bloc doesn't emmit state


I am trying to use bloc in a command line application, but the bloc doesn't emmit new states.

I was expecting to go to the function 'porHacer', the initial state is EstadoInicial, which takes me to the function estadoInicial, there I add the event JugadorAgregado which emmits a new state, Lobby, but that new state is never reflected and I never go to porHacer. This a very simplified code, but it gives the intention

import 'dart:io';

import 'package:dart_console/dart_console.dart';
import 'dart:async';
import 'package:bloc/bloc.dart';

sealed class Estado {}

class EstadoInicial extends Estado {}

class Lobby extends Estado {}

sealed class Evento {}

class JugadorAgregado extends Evento {}

class JuegoBloc extends Bloc<Evento, Estado> {
  JuegoBloc() : super(EstadoInicial()) {
    on<JugadorAgregado>(_onJugadorAgregado);
  }

  FutureOr<void> _onJugadorAgregado(event, emit) {
    emit(Lobby());
  }
}

final consola = Console();
final bloc = JuegoBloc();

void main(List<String> arguments) {
  do {
    var estado = bloc.state;
    // ignore: unused_local_variable
    var noImporta = switch (estado) {
      (EstadoInicial _) => estadoInicial(),
      _ => porHacer(),
    };
  } while (true);
}

void estadoInicial() {
  print('entré al estado inicial');
  bloc.add(JugadorAgregado());
  Future.delayed(Duration(seconds: 2));
}

void porHacer() {
  print('Aún no implementado');
  exit(0);
}


Solution

  • Your understanding of how bloc works and the logic of your code regarding it is absolutely correct.

    However, there may be some misunderstanding about futures.

    When you do

    Future.delayed(const Duration(seconds: 2));
    

    you're discarding this future, so it's in practice equivalent to doing nothing.

    To effectively wait for 2 seconds, you need to await it:

    await Future.delayed(const Duration(seconds: 2));
    

    That said, change your estadoInicial function to

    Future<void> estadoInicial() async {
      print('entré al estado inicial');
      bloc.add(JugadorAgregado());
      await Future.delayed(Duration(seconds: 2));
    }
    

    Since estadoInicial now returns a Future, change your main function to

    //             Add `async` here:  vvvvv
    void main(List<String> arguments) async {
      do {
        var estado = bloc.state;
    
        // Use a switch-statement here instead of a 
        // switch-expression, since only `estadoInicial`
        // is a function that returns a Future
        switch (estado) {
          case (EstadoInicial _):
            {
              // Await it
              await estadoInicial();
            }
          default:
            {
              porHacer();
            }
        }
      } while (true);
    }
    

    Now the code correctly outputs "Aún no implementado".