Let’s take a look at CounterPage
next!
The CounterPage
widget is responsible for creating a CounterCubit
(which we will look at next) and providing it to the CounterView
.
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../counter.dart'; import 'counter_view.dart'; /// {@template counter_page} /// A [StatelessWidget] which is responsible for providing a /// [CounterCubit] instance 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: (_) => CounterCubit(), child: CounterView(), ); } } Copy to clipboardErrorCopied
Note: It’s important to separate or decouple the creation of a
Cubit
from the consumption of aCubit
in order to have code that is much more testable and reusable.
The CounterCubit
class will expose two methods:
increment
: adds 1 to the current statedecrement
: subtracts 1 from the current stateThe type of state the CounterCubit
is managing is just an int
and the initial state is 0
.
import 'package:bloc/bloc.dart'; /// {@template counter_cubit} /// A [Cubit] which manages an [int] as its state. /// {@endtemplate} class CounterCubit extends Cubit<int> { /// {@macro counter_cubit} CounterCubit() : super(0); /// Add 1 to the current state. void increment() => emit(state + 1); /// Subtract 1 from the current state. void decrement() => emit(state - 1); } Copy to clipboardErrorCopied
Tip: Use the VSCode Extension or IntelliJ Plugin to create new cubits automatically.
Next, let’s take a look at the CounterView
which will be responsible for consuming the state and interacting with the CounterCubit
.
The CounterView
is responsible for rendering the current count and rendering two FloatingActionButtons to increment/decrement the counter.
import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../counter.dart'; /// {@template counter_view} /// A [StatelessWidget] which reacts to the provided /// [CounterCubit] state and notifies it in response to user input. /// {@endtemplate} class CounterView extends StatelessWidget { @override Widget build(BuildContext context) { final textTheme = Theme.of(context).textTheme; return Scaffold( appBar: AppBar(title: const Text('Counter')), body: Center( child: BlocBuilder<CounterCubit, int>( builder: (context, state) { return Text('$state', style: textTheme.headline2); }, ), ), floatingActionButton: Column( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: <Widget>[ FloatingActionButton( key: const Key('counterView_increment_floatingActionButton'), child: const Icon(Icons.add), onPressed: () => context.read<CounterCubit>().increment(), ), const SizedBox(height: 8), FloatingActionButton( key: const Key('counterView_decrement_floatingActionButton'), child: const Icon(Icons.remove), onPressed: () => context.read<CounterCubit>().decrement(), ), ], ), ); } } Copy to clipboardErrorCopied
A BlocBuilder
is used to wrap the Text
widget in order to update the text any time the CounterCubit
state changes. In addition, context.read<CounterCubit>()
is used to look-up the closest CounterCubit
instance.
Note: Only the Text
widget is wrapped in a BlocBuilder
because that is the only widget that needs to be rebuilt in response to state changes in the CounterCubit
. Avoid unnecessarily wrapping widgets that don’t need to be rebuilt when a state changes.
Add counter.dart
to export all the public facing parts of the counter feature.
export 'cubit/counter_cubit.dart'; export 'view/counter_page.dart'; Copy to clipboardErrorCopied
That’s it! We’ve separated the presentation layer from the business logic layer. The CounterView
has no idea what happens when a user presses a button; it just notifies the CounterCubit
. Furthermore, the CounterCubit
has no idea what is happening with the state (counter value); it’s simply emitting new states in response to the methods being called.
We can run our app with flutter run
and can view it on our device or simulator/emulator.
The full source (including unit and widget tests) for this example can be found here.
Thank for reading!
References form here
You need to login in order to like this post: click here
YOU MIGHT ALSO LIKE