Created
March 4, 2023 10:33
-
-
Save LiamKarlMitchell/db2e2eb3c3ddb13127f0b166fa648eb5 to your computer and use it in GitHub Desktop.
Flutter Bloc Delayed Event Emit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This code is distributed under the MIT License. | |
// Copyright (c) 2018 Felix Angelov. | |
// You can find the original at https://github.com/felangel/bloc. | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_bloc/flutter_bloc.dart'; | |
import 'dart:math'; | |
var rng = Random(); | |
void main() { | |
Bloc.observer = AppBlocObserver(); | |
runApp(const App()); | |
} | |
/// Custom [BlocObserver] that observes all bloc and cubit state changes. | |
class AppBlocObserver extends BlocObserver { | |
@override | |
void onChange(BlocBase bloc, Change change) { | |
super.onChange(bloc, change); | |
if (bloc is Cubit) print(change); | |
} | |
@override | |
void onTransition(Bloc bloc, Transition transition) { | |
super.onTransition(bloc, transition); | |
print(transition); | |
} | |
} | |
/// {@template app} | |
/// A [StatelessWidget] that: | |
/// * uses [bloc](https://pub.dev/packages/bloc) and | |
/// [flutter_bloc](https://pub.dev/packages/flutter_bloc) | |
/// to manage the state of a counter and the app theme. | |
/// {@endtemplate} | |
class App extends StatelessWidget { | |
/// {@macro app} | |
const App({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return BlocProvider( | |
create: (_) => ThemeCubit(), | |
child: const AppView(), | |
); | |
} | |
} | |
/// {@template app_view} | |
/// A [StatelessWidget] that: | |
/// * reacts to state changes in the [ThemeCubit] | |
/// and updates the theme of the [MaterialApp]. | |
/// * renders the [CounterPage]. | |
/// {@endtemplate} | |
class AppView extends StatelessWidget { | |
/// {@macro app_view} | |
const AppView({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return BlocBuilder<ThemeCubit, ThemeData>( | |
builder: (_, theme) { | |
return MaterialApp( | |
theme: theme, | |
home: const CounterPage(), | |
); | |
}, | |
); | |
} | |
} | |
/// {@template counter_page} | |
/// A [StatelessWidget] that: | |
/// * provides a [CounterBloc] to the [CounterView]. | |
/// {@endtemplate} | |
class CounterPage extends StatelessWidget { | |
/// {@macro counter_page} | |
const CounterPage({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return BlocProvider( | |
create: (_) => CounterBloc(), | |
child: const CounterView(), | |
); | |
} | |
} | |
/// {@template counter_view} | |
/// A [StatelessWidget] that: | |
/// * demonstrates how to consume and interact with a [CounterBloc]. | |
/// {@endtemplate} | |
class CounterView extends StatelessWidget { | |
/// {@macro counter_view} | |
const CounterView({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: const Text('Counter')), | |
body: Center( | |
child: BlocBuilder<CounterBloc, int>( | |
builder: (context, count) { | |
return Text('$count', style: Theme.of(context).textTheme.displayLarge); | |
}, | |
), | |
), | |
floatingActionButton: Column( | |
crossAxisAlignment: CrossAxisAlignment.end, | |
mainAxisAlignment: MainAxisAlignment.end, | |
children: <Widget>[ | |
FloatingActionButton( | |
child: const Icon(Icons.add), | |
onPressed: () => context.read<CounterBloc>().add(Increment()), | |
), | |
const SizedBox(height: 4), | |
FloatingActionButton( | |
child: const Icon(Icons.remove), | |
onPressed: () => context.read<CounterBloc>().add(Decrement()), | |
), | |
const SizedBox(height: 4), | |
FloatingActionButton( | |
child: const Icon(Icons.brightness_6), | |
onPressed: () => context.read<ThemeCubit>().toggleTheme(), | |
), | |
], | |
), | |
); | |
} | |
} | |
/// Event being processed by [CounterBloc]. | |
abstract class CounterEvent {} | |
/// Notifies bloc to increment state. | |
class Increment extends CounterEvent {} | |
/// Notifies bloc to decrement state. | |
class Decrement extends CounterEvent {} | |
/// {@template counter_bloc} | |
/// A simple [Bloc] that manages an `int` as its state. | |
/// {@endtemplate} | |
class CounterBloc extends Bloc<CounterEvent, int> { | |
/// {@macro counter_bloc} | |
CounterBloc() : super(0) { | |
on<Increment>((event, emit) => Future.delayed(Duration(seconds: rng.nextInt(5)), () { | |
print('One second has passed.'); // Prints after 1 second. | |
emit(state + 1); | |
})); | |
on<Decrement>((event, emit) => Future.delayed(Duration(seconds: rng.nextInt(5)), () { | |
print('One second has passed.'); // Prints after 1 second. | |
emit(state - 1); | |
})); | |
} | |
} | |
/// {@template brightness_cubit} | |
/// A simple [Cubit] that manages the [ThemeData] as its state. | |
/// {@endtemplate} | |
class ThemeCubit extends Cubit<ThemeData> { | |
/// {@macro brightness_cubit} | |
ThemeCubit() : super(_lightTheme); | |
static final _lightTheme = ThemeData( | |
floatingActionButtonTheme: const FloatingActionButtonThemeData( | |
foregroundColor: Colors.white, | |
), | |
brightness: Brightness.light, | |
); | |
static final _darkTheme = ThemeData( | |
floatingActionButtonTheme: const FloatingActionButtonThemeData( | |
foregroundColor: Colors.black, | |
), | |
brightness: Brightness.dark, | |
); | |
/// Toggles the current brightness between light and dark. | |
void toggleTheme() { | |
emit(state.brightness == Brightness.dark ? _lightTheme : _darkTheme); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment