¡Perfecto! Vamos a aprender BLoC paso a paso, empezando desde lo más básico para que entiendas el flujo de trabajo y las partes fundamentales. Vamos a construir una app simple de contador, ya que es un excelente punto de partida para entender cómo funcionan eventos, estados, y cómo conectarlos con la UI.
Paso 1: Configurar BLoC en el proyecto
1. Agrega el paquete flutter_bloc a tu proyecto:
Abre el archivo pubspec.yaml y añade:
dependencies:
flutter_bloc: ^8.1.2
Luego, ejecuta:
flutter pub get
2. Estructura del proyecto:
Organiza tu proyecto para que el código sea modular y fácil de entender. Por ejemplo:
lib/
├── bloc/
│ ├── counter_bloc.dart
│ ├── counter_event.dart
│ └── counter_state.dart
├── main.dart
└── ui/
└── counter_screen.dart
Paso 2: Crea los componentes del BLoC
1. Define los eventos
Los eventos son acciones que el usuario dispara, como presionar un botón. Aquí definiremos los eventos para incrementar y decrementar el contador.
// lib/bloc/counter_event.dart
abstract class CounterEvent {}
// Evento para incrementar el contador
class IncrementCounter extends CounterEvent {}
// Evento para decrementar el contador
class DecrementCounter extends CounterEvent {}
2. Define los estados
Los estados son el resultado que queremos mostrar en la UI. En este caso, el estado será el valor actual del contador.
// lib/bloc/counter_state.dart
abstract class CounterState {}
// Estado que representa el valor del contador
class CounterValueState extends CounterState {
final int counterValue;
CounterValueState(this.counterValue);
}
3. Crea el BLoC
El BLoC conecta los eventos con los estados. Aquí procesamos la lógica de negocio: al recibir un evento, actualizamos el estado del contador.
// lib/bloc/counter_bloc.dart
import 'package:flutter_bloc/flutter_bloc.dart';
import 'counter_event.dart';
import 'counter_state.dart';
class CounterBloc extends Bloc<CounterEvent, CounterState> {
CounterBloc() : super(CounterValueState(0)) {
// Maneja IncrementCounter
on<IncrementCounter>((event, emit) {
final currentState = state as CounterValueState;
emit(CounterValueState(currentState.counterValue + 1));
});
// Maneja DecrementCounter
on<DecrementCounter>((event, emit) {
final currentState = state as CounterValueState;
emit(CounterValueState(currentState.counterValue - 1));
});
}
}
Paso 3: Conectar el BLoC con la UI
1. Configura el BlocProvider
El BlocProvider es necesario para crear y exponer el BLoC a la UI. Esto lo hacemos en el archivo main.dart:
// lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'bloc/counter_bloc.dart';
import 'ui/counter_screen.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlocProvider(
create: (context) => CounterBloc(),
child: CounterScreen(),
),
);
}
}
2. Construye la UI
La UI usará BlocBuilder para escuchar los estados del BLoC y actualizarse automáticamente cuando cambien.
// lib/ui/counter_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../bloc/counter_bloc.dart';
import '../bloc/counter_event.dart';
import '../bloc/counter_state.dart';
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counterBloc = context.read<CounterBloc>();
return Scaffold(
appBar: AppBar(title: Text('Contador con BLoC')),
body: Center(
child: BlocBuilder<CounterBloc, CounterState>(
builder: (context, state) {
final counterValue = (state as CounterValueState).counterValue;
return Text(
'Valor: $counterValue',
style: TextStyle(fontSize: 32),
);
},
),
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () => counterBloc.add(IncrementCounter()),
child: Icon(Icons.add),
),
SizedBox(width: 10),
FloatingActionButton(
onPressed: () => counterBloc.add(DecrementCounter()),
child: Icon(Icons.remove),
),
],
),
);
}
}
Paso 4: Prueba tu app
1. Ejecuta la app.
2. Toca los botones + y - para disparar los eventos IncrementCounter y DecrementCounter.
3. Observa cómo la UI se actualiza automáticamente con los nuevos valores del contador.
Paso 5: Explicación del flujo
1. El usuario toca un botón (+ o -).
2. La UI dispara un evento (por ejemplo, IncrementCounter).
3. El evento llega al CounterBloc, que ejecuta la lógica para actualizar el estado.
4. El BLoC emite un nuevo estado (CounterValueState con un nuevo valor).
5. BlocBuilder escucha el cambio de estado y reconstruye la UI con el nuevo valor.
¿Qué aprendiste aquí?
1. Eventos: Representan lo que ocurre en la app (acciones del usuario).
2. Estados: Representan cómo debe lucir la app tras un evento.
3. BLoC: Es el puente entre eventos y estados, manejando la lógica de negocio.
4. BlocProvider: Expone el BLoC a los widgets.
5. BlocBuilder: Reconstruye la UI automáticamente cuando cambia el estado.
Próximos pasos
1. Haz un segundo ejemplo: Amplía esta app para que el contador no solo sume/resta, sino que tenga un botón de “reiniciar”.
2. Manejo de estados múltiples: Crea una lista de tareas con estados como “pendiente” o “completada”.
3. Firebase: Integra Firebase para sincronizar el contador o datos entre dispositivos.
Si necesitas ayuda para el siguiente paso, ¡avísame! 😊
Comentarios
Publicar un comentario