Bloc example
Source code Click here to view the full source code of this example
Bloc is one of the most widely used libraries in the Flutter ecosystem, which is why we’ve included an example to demonstrate its integration.
Our example demonstrates how to provide a light/dark theme Cubit using Disco.
Dependency
This is the flutter_bloc
version used in this example:
dependencies: flutter_bloc: ^9.0.0
File structure
Let’s look at the file structure:
Directorycubit
- theme_cubit.dart
Directorydi
- providers.dart
Directoryui
Directoryscreens
- theme_switcher_page.dart
Directorywidgets
- themed_button.dart
- main.dart
ThemeCubit
Let’s get started by writing a class that extends Cubit<bool>
.
import 'package:flutter_bloc/flutter_bloc.dart';
/// ThemeCubit manages the light/dark theme stateclass ThemeCubit extends Cubit<bool> { ThemeCubit() : super(false); // false means light, true means dark theme
void toggleTheme() => emit(!state);}
Providers
In a separate file, we define the providers.
import 'package:bloc_example/cubit/theme_cubit.dart';import 'package:disco/disco.dart';
final themeProvider = Provider((context) => ThemeCubit());
ThemedButton
We also define a button where we inject the themeProvider
. We want it to display different texts based on the current value.
import 'package:bloc_example/di/providers.dart';import 'package:flutter/material.dart';import 'package:flutter_bloc/flutter_bloc.dart';
class ThemedButton extends StatelessWidget { const ThemedButton({super.key});
@override Widget build(BuildContext context) { final themeCubit = themeProvider.of(context); return BlocBuilder( bloc: themeCubit, builder: (context, bool isDarkMode) { return ElevatedButton( onPressed: themeCubit.toggleTheme, style: ElevatedButton.styleFrom( backgroundColor: isDarkMode ? Colors.grey[800] : Colors.lightBlue, foregroundColor: isDarkMode ? Colors.white : Colors.black, padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), child: Text( isDarkMode ? 'Switch to Light Mode' : 'Switch to Dark Mode', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ); }, ); }}
ThemeSwitcherPage
We define the page for our example. It contains a ThemedButton
.
import 'package:bloc_example/ui/widgets/themed_button.dart';import 'package:flutter/material.dart';
class ThemeSwitcherPage extends StatelessWidget { const ThemeSwitcherPage({super.key});
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Cubit Theme Example')), body: const Center( child: ThemedButton(), ), ); }}
App
Let’s finish the example by adding the following code in our main.dart
.
import 'package:bloc_example/di/providers.dart';import 'package:bloc_example/ui/screens/theme_switcher_page.dart';import 'package:disco/disco.dart';import 'package:flutter/material.dart';import 'package:flutter_bloc/flutter_bloc.dart';
void main() { runApp(const MyApp());}
class MyApp extends StatelessWidget { const MyApp({super.key});
@override Widget build(BuildContext context) { return ProviderScope( providers: [themeProvider], child: Builder( builder: (context) { return BlocBuilder( // NB: When injecting the cubit, the context has to be a descendant // of ProviderScope (and not what MyApp.build provides). bloc: themeProvider.of(context), builder: (context, bool isDarkMode) { return MaterialApp( theme: isDarkMode ? ThemeData.dark().copyWith(primaryColor: Colors.blueGrey) : ThemeData.light() .copyWith(primaryColor: Colors.lightBlue), home: const ThemeSwitcherPage(), ); }, ); }, ), ); }}