BLoC — qué es, Business Logic Component en Flutter

Autor: IT Sectr Publicado: 2026-02-19 Tiempo de lectura: 7 min

BLoC (Business Logic Component) — un patrón de gestión de estado para Flutter, presentado por Google en 2018 en DartConf. BLoC separa la lógica de negocio de la interfaz de usuario a través de flujos reactivos (Stream): la UI envía un Event, BLoC lo procesa y devuelve un nuevo State mediante Stream. Según pub.dev, el paquete flutter_bloc ha superado los 11 mil likes y se utiliza en miles de aplicaciones Flutter.

Puntos clave

  • Event — señal de entrada que describe una acción: pulsar botón, cargar datos
  • State — estado de salida de la UI: datos cargados, error, carga
  • Bloc — clase principal que recibe Event y devuelve State mediante Stream
  • Cubit — versión simplificada de Bloc sin Event, que llama funciones directamente
  • BlocProvider — widget de Flutter para inyectar Bloc en el árbol de widgets

¿Qué es BLoC?

BLoC (Business Logic Component) — un patrón arquitectónico para Flutter en el que la lógica de negocio se extrae en una clase separada, aislada de la UI. BLoC recibe datos de entrada a través de un flujo de eventos (Event) y produce datos de salida a través de un flujo de estados (State). La capa de presentación (Widget) solo se suscribe al flujo de State y renderiza la UI, sin ejecutar nunca la lógica de negocio directamente.

El concepto de BLoC se basa en la programación reactiva y el patrón Observer. Cada componente BLoC es un módulo separado con un contrato claro: un conjunto conocido de Events (lo que puede suceder) y un conjunto conocido de States (lo que se puede mostrar). Un desarrollador no puede "accidentalmente" cambiar el estado desde la UI — solo a través de un Event específico. Esto hace que el código sea predecible y comprobable.

Según la encuesta Flutter Community 2025, BLoC ocupa el segundo lugar en popularidad entre las soluciones de gestión de estado en Flutter después de Provider. Ventajas principales: tipificado fuerte, aislamiento de lógica, soporte integrado de Stream, rico ecosistema de utilidades (BlocProvider, BlocListener, BlocSelector).

Arquitectura de BLoC: Event → Bloc → State

La arquitectura BLoC se construye alrededor de tres entidades: Event (entrada), Bloc (procesador) y State (salida). El Widget envía un Event mediante el método add(). Bloc recibe el Event en el método mapEventToState o on<Event>, ejecuta la lógica de negocio y emite un nuevo State mediante yield. El Widget recibe el State a través de un Stream y se reconstruye.

Dart
abstract class CounterEvent {}

class Increment extends CounterEvent {}
class Decrement extends CounterEvent {}

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    if (event is Increment) {
      yield state + 1;
    } else if (event is Decrement) {
      yield state - 1;
    }
  }
}

Seguridad de tipos: Bloc está parametrizado con dos tipos — Event y State. El compilador de Dart verifica que el Widget solo llame a Events declarados y que Bloc solo devuelva States declarados. Los errores de tiempo de ejecución como "Action desconocido" quedan eliminados.

Cierre y Dispose: Bloc implementa la interfaz Closeable. Cuando un widget se destruye, Bloc cierra automáticamente el Stream mediante el método close(). Las fugas de suscripciones reactivas son imposibles — BlocProvider gestiona el ciclo de vida de Bloc, vinculándolo a una ruta o página.

Bloc y Cubit: comparación

Cubit es una implementación simplificada de Bloc sin Event, presentada en el paquete flutter_bloc 6.0. Cubit declara métodos directamente en lugar de clases Event: increment(), fetchData(). Internamente, Cubit utiliza el mismo mecanismo basado en Stream pero oculta la capa de Event. Esto reduce el boilerplate entre un 40-50% para escenarios simples.

CaracterísticaBlocCubit
Clases EventObligatoriasNo necesarias
BoilerplateAltoBajo
Seguimiento de accionesMediante tipo EventSolo nombre del método
Ideal paraEscenarios complejosEstados simples
AnalíticaAutomática por EventManual

Cuándo elegir Cubit: estado con 2-3 variantes (loading, loaded, error), formularios simples, contadores, estados de UI (abierto/cerrado). Cuándo elegir Bloc: lógica de negocio compleja con múltiples acciones: procesamiento de pedidos, autorización, sincronización de datos. Bloc proporciona trazado detallado de cada acción a través de Event — cada llamada se registra en BlocObserver.

BlocObserver — un observador global que rastrea todos los Bloc y Cubit en la aplicación. Permite registrar Event, State, errores y transiciones. Simplemente conecta una instancia: Bloc.observer = AppBlocObserver(), y todo el trazado del estado de la aplicación está disponible centralizadamente.

BlocProvider y BlocBuilder

BlocProvider — un InheritedWidget de flutter_bloc que proporciona un Bloc a los widgets hijos. Cuando se inicializa un widget, BlocProvider crea un Bloc, y cuando se destruye — lo cierra automáticamente mediante close(). BlocProvider puede colocarse a nivel de MaterialApp (Bloc global) o a nivel de una ruta específica (Bloc local).

Dart
BlocProvider(
  create: (context) => CounterBloc(),
  child: Column(
    children: [
      BlocBuilder<CounterBloc, int>(
        builder: (context, state) => Text('$state'),
      ),
      ElevatedButton(
        onPressed: () => context.read<CounterBloc>().add(Increment()),
        child: Text('+'),
      ),
    ],
  ),
)

BlocBuilder — un widget que reconstruye la UI en cada nuevo State. BlocListener — para efectos secundarios (procesar un State una vez, sin reconstruir la UI): mostrar un SnackBar, navegar a otra pantalla. BlocConsumer — una combinación de Builder y Listener para casos donde se necesita tanto reconstrucción como efecto secundario. BlocSelector — para reconstrucción selectiva solo cuando cambia un campo específico del State.

MultiBlocProvider — un widget para BlocProviders anidados sin aumentar niveles de anidación. Una aplicación Flutter con 10-15 Blocs usa MultiBlocProvider a nivel raíz para registrar todos los Blocs disponibles para toda la aplicación: AuthenticationBloc, CartBloc, SettingsBloc.

Pruebas de BLoC

BLoC se prueba de forma aislada sin widgets de Flutter. Simplemente importa el paquete Dart flutter_test y el paquete bloc_test. El escenario de prueba: crear un Bloc, añadir un Event, verificar el State. blocTest — una utilidad que automatiza la secuencia: build → act → expect.

Dart
blocTest<CounterBloc, int>(
  'emits [1] when Increment is added',
  build: () => CounterBloc(),
  act: (bloc) => bloc.add(Increment()),
  expect: () => [1],
)

Simulación (Mocking): Un Bloc que depende de un repositorio o API se prueba con mocks mediante mocktail. El repositorio se simula a nivel de abstracción, y el Bloc recibe las dependencias simuladas a través del constructor. Hydrated Bloc — una extensión para la persistencia/restauración automática del estado en almacenamiento local. Se prueba con HydratedBlocStorage y un almacenamiento de archivos temporal.

BLoC en producción

Carpetas y archivos: una estructura típica de proyecto Flutter con BLoC: bloc/counter_bloc.dart, bloc/counter_event.dart, bloc/counter_state.dart. Para 30+ pantallas, se recomienda la agrupación por funcionalidades: features/auth/bloc/, features/cart/bloc/. Cada Bloc es un archivo separado, cada Event y State — ya sea en archivos separados o en uno solo con el Bloc.

Rendimiento: BLoC no crea sobrecarga para Streams vacíos. BlocBuilder usa buildWhen para filtrar reconstrucciones — el widget solo se actualiza cuando cambia una condición específica. Close garantiza que los Blocs inactivos no consuman memoria. Según Flutter DevTools, BLoC añade menos del 1% al tamaño del bundle.

Migración desde Provider: BLoC coexiste fácilmente con Provider en el mismo proyecto. Migración gradual: primero reemplaza los Providers más complejos por Bloc, luego el resto. BlocProvider es compatible con el árbol de Provider: los widgets antiguos pueden usar Provider, los nuevos — BlocProvider, dentro de una misma aplicación.

Preguntas frecuentes

¿En qué se diferencia BLoC de Provider en Flutter?

BLoC usa Event + Stream para el aislamiento de la lógica de negocio y el tipificado fuerte. Provider es un envoltorio alrededor de InheritedWidget para inyección simple de dependencias y ChangeNotifier. BLoC es mejor para escenarios complejos con múltiples estados, Provider — para estados locales de UI. BLoC requiere más boilerplate pero proporciona trazabilidad completa mediante Events.

¿Qué es Hydrated Bloc?

Hydrated Bloc es una extensión del paquete hydrated_bloc que guarda automáticamente el último State en almacenamiento local (Hive por defecto). Cuando la aplicación se reinicia, el Bloc restaura el estado guardado en lugar del inicial. Esto resuelve el problema de persistencia sin llamadas manuales de guardado: inicio de sesión, carrito, configuración se guardan automáticamente entre sesiones.

¿Cómo manejar errores en BLoC?

Un error en BLoC se maneja mediante try-catch dentro de mapEventToState o on<Event>. Ante un error, Bloc devuelve un State de error: yield LoadError(error.message). En la UI, BlocListener o BlocConsumer verifica el State por el tipo de error y muestra un SnackBar o diálogo. BlocObserver registra globalmente todas las excepciones no manejadas.

¿Se puede usar BLoC con otros frameworks?

BLoC es un patrón específico de Flutter ya que usa Dart Stream y widgets de Flutter. El concepto Event → Bloc → State puede adaptarse para AngularDart y Server-side Dart, pero el ecosistema principal (BlocProvider, BlocBuilder, BlocObserver) está vinculado a Flutter. Para React Native, usa Redux o MobX; para SwiftUI, usa Combine + MVVM.

¿Qué elegir: Bloc o Cubit?

Cubit — para estados simples (contador, toggle, formulario con 2-3 campos). Bloc — para lógica compleja (feed de noticias, procesamiento de pedidos, autorización). La regla principal: si necesitas trazado de cada acción (Event) para analítica o depuración — elige Bloc. Si los métodos que cambian el estado son suficientes — elige Cubit. Ambos patrones pueden coexistir en el mismo proyecto.

Resumen

  • BLoC — patrón de gestión de estado en Flutter mediante Event → Stream → State
  • Event — acción (presionar, cargar), State — reacción (datos, error, carga)
  • Cubit — versión simplificada sin Event, hasta 50% menos boilerplate
  • BlocProvider — inyección de Bloc en el árbol de widgets con cierre automático
  • BlocObserver — monitoreo global de todos los Bloc y Cubit en la aplicación
  • Hydrated Bloc — persistencia automática del estado mediante Hive
  • blocTest — utilidad para pruebas unitarias de Bloc aisladas de Flutter

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también