Flutter BLoc Counter App: A Step-by-Step Guide
UMAIR SALEEM
MERN Stack Developer | Angular Developer | Flutter App Developer | Hybrid Mobile App Developer | Backend Developer | Node Js | ExpressJs/NestJs | ReactJs/NextJs
Flutter is a popular framework for building cross-platform mobile applications. One of the advantages of Flutter is its ability to use a pattern called the BLoC (Business Logic Component) pattern to manage the state of the application. In this article, we will build a simple Flutter counter app using the BLoC pattern.
The app will have a counter that can be incremented or decremented by the user. We will use the BLoc pattern to manage the state of the counter, and the UI will be built using the Flutter widget library.
utter create flutter_counter
This will create a new Flutter project called "flutter_counter" in the current directory.
Next, navigate to the project directory and open the "lib" folder. This is where we will write the code for our app.
We can then go ahead and replace the contents of?pubspec.yaml?with
name: flutter_counter
publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
? sdk: ">=2.19.6 <3.0.0"
dependencies:
? flutter:
? ? sdk: flutter
? cupertino_icons: ^1.0.2
? flutter_bloc: ^8.1.2
? bloc: ^8.1.1
dev_dependencies:
? flutter_test:
? ? sdk: flutter
? flutter_lints: ^2.0.0
flutter:
? uses-material-design: true
Project Structure
├── lib
│ ├── counter
│ │ ├── counter.dart
│ │ ├── cubit
│ │ │ └── counter_cubit.dart
│ │ └── view
│ │ ├── counter_page.dart
│ │ └── counter_view.dart
│ ├── counter_observer.dart
│ └── main.dart
├── pubspec.yaml
Create a new file called "counter_observer.dart". This file will contain a BlocObserver that we will use to log the state changes of our counter.
import 'dart:developer';
import 'package:bloc/bloc.dart';
class CounterObserver extends BlocObserver {
? const CounterObserver();
? @override
? void onChange(BlocBase<dynamic> bloc, Change<dynamic> change) {
? ? super.onChange(bloc, change);
? ? log("${bloc.runtimeType} $change");
? }
}
This observer will print the state changes of our counter to the console whenever a change occurs.
Next, open the "main.dart" file and add the following code to the top:
领英推荐
import 'package:bloc/bloc.dart'
import 'package:flutter/material.dart';
import 'package:flutter_counter/counter/view/counter_page.dart';
import 'package:flutter_counter/counter_observer.dart';
void main() {
? Bloc.observer = const CounterObserver();
? runApp(const CounterApp());
}
This code sets up our app to use the CounterObserver we just created and starts the app by running the CounterApp widget.
Now, let's create the CounterApp widget. Create a new file called "app.dart" and add the following code:
import 'package:bloc/bloc.dart'
import 'package:flutter/material.dart';
import 'package:flutter_counter/counter/view/counter_page.dart';
import 'package:flutter_counter/counter_observer.dart';
void main() {
? Bloc.observer = const CounterObserver();
? runApp(const CounterApp());
}
class CounterApp extends StatelessWidget {
? const CounterApp({super.key});
? @override
? Widget build(BuildContext context) {
? ? return MaterialApp(
? ? ? debugShowCheckedModeBanner: false,
? ? ? title: 'Bloc Counter',
? ? ? theme: ThemeData(
? ? ? ? primarySwatch: Colors.orange,
? ? ? ),
? ? ? home: const CounterPage(),
? ? );
? }
}
This code creates a new MaterialApp widget and sets the home page to the CounterPage widget.
Next, let's create the CounterPage widget. Create a new folder called "counter" in the "lib" directory, and inside that folder, create a new file called "counter.dart". Add the following code to that file:
import 'package:flutter/material.dart'
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_counter/counter/counter.dart';
class CounterPage extends StatelessWidget {
? const CounterPage({Key? key}) : super(key: key);
? @override
? Widget build(BuildContext context) {
? ? return BlocProvider(
? ? ? create: (_) => CounterCubit(),
? ? ? child: const CounterView(),
? ? );
? }
}
CounterCubit is a class that extends the Cubit class from the bloc package. It is responsible for maintaining the state of the counter and exposing methods to increment and decrement the counter value. The emit method is used to update the state of the counter whenever a change occurs.
import 'package:bloc/bloc.dart'
class CounterCubit extends Cubit<int> {
? CounterCubit() : super(0);
? void increment() => emit(state + 1);
? void decrement() => emit(state - 1);
}
CounterView is a stateless widget that renders the UI of the counter app. It uses BlocBuilder from the flutter_bloc package to rebuild the UI whenever the state of CounterCubit changes. The BuildContext object is used to obtain an instance of CounterCubit via context.read<CounterCubit>(). The increment and decrement methods are invoked via the onPressed callback of the FloatingActionButton widgets.
import 'package:flutter/material.dart'
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_counter/counter/cubit/counter_cubit.dart';
class CounterView extends StatelessWidget {
? const CounterView({super.key});
? @override
? Widget build(BuildContext context) {
? ? final textTheme = Theme.of(context).textTheme;
? ? return Scaffold(
? ? ? appBar: AppBar(
? ? ? ? title: const Text("Bloc Counter"),
? ? ? ),
? ? ? body: Center(
? ? ? ? child: BlocBuilder<CounterCubit, int>(builder: (context, state) {
? ? ? ? ? return Text(
? ? ? ? ? ? "$state",
? ? ? ? ? ? style: textTheme.displayMedium,
? ? ? ? ? );
? ? ? ? }),
? ? ? ),
? ? ? floatingActionButton: Row(
? ? ? ? mainAxisAlignment: MainAxisAlignment.spaceAround,
? ? ? ? children: [
? ? ? ? ? FloatingActionButton(
? ? ? ? ? ? onPressed: () => context.read<CounterCubit>().increment(),
? ? ? ? ? ? child: const Icon(Icons.add),
? ? ? ? ? ),
? ? ? ? ? FloatingActionButton(
? ? ? ? ? ? onPressed: () => context.read<CounterCubit>().decrement(),
? ? ? ? ? ? child: const Icon(Icons.remove),
? ? ? ? ? )
? ? ? ? ],
? ? ? ),
? ? );
? }
}
Using BLoC architecture can make your Flutter apps more efficient, scalable, and easier to maintain. By separating the business logic from the presentation layer, you can write clean and reusable code that can be easily tested and modified. In this article, we learned how to use the CounterCubit and CounterView to implement a simple counter app using BLoC. I hope you found this article useful and informative. Happy coding!