Skip to content

Latest commit

 

History

History
138 lines (81 loc) · 6.27 KB

fluttercountertutorial.md

File metadata and controls

138 lines (81 loc) · 6.27 KB

Flutter Counter Tutorial

beginner

In the following tutorial, we're going to build a Counter in Flutter using the Bloc library.

demo

Key Topics

Setup

We'll start off by creating a brand new Flutter project

flutter create flutter_counter

We can then go ahead and replace the contents of pubspec.yaml with

pubspec.yaml

and then install all of our dependencies

flutter packages get

Project Structure

├── lib
│   ├── app.dart
│   ├── counter
│   │   ├── counter.dart
│   │   ├── cubit
│   │   │   └── counter_cubit.dart
│   │   └── view
│   │       ├── counter_page.dart
│   │       └── counter_view.dart
│   ├── counter_observer.dart
│   └── main.dart
├── pubspec.lock
├── pubspec.yaml

The application uses a feature-driven directory structure. This project structure enables us to scale the project by having self-contained features. In this example we will only have a single feature (the counter itself) but in more complex applications we can have hundreds of different features.

BlocObserver

The first thing we're going to take a look at is how to create a BlocObserver which will help us observe all state changes in the application.

Let's create lib/counter_observer.dart:

counter_observer.dart

In this case, we're only overriding onChange to see all state changes that occur.

?> Note: onChange works the same way for both Bloc and Cubit instances.

main.dart

Next, let's replace the contents of main.dart with:

main.dart

We're initializing the CounterObserver we just created and calling runApp with the CounterApp widget which we'll look at next.

Counter App

Let's create lib/app.dart:

CounterApp will be a MaterialApp and is specifying the home as CounterPage.

app.dart

?> Note: We are extending MaterialApp because CounterApp is a MaterialApp. In most cases, we're going to be creating StatelessWidget or StatefulWidget instances and composing widgets in build but in this case there are no widgets to compose so it's simpler to just extend MaterialApp.

Let's take a look at CounterPage next!

Counter Page

Let's create lib/counter/view/counter_page.dart:

The CounterPage widget is responsible for creating a CounterCubit (which we will look at next) and providing it to the CounterView.

counter_page.dart

?> Note: It's important to separate or decouple the creation of a Cubit from the consumption of a Cubit in order to have code that is much more testable and reusable.

Counter Cubit

Let's create lib/counter/cubit/counter_cubit.dart:

The CounterCubit class will expose two methods:

  • increment: adds 1 to the current state
  • decrement: subtracts 1 from the current state

The type of state the CounterCubit is managing is just an int and the initial state is 0.

counter_cubit.dart

?> 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.

Counter View

Let's create lib/counter/view/counter_view.dart:

The CounterView is responsible for rendering the current count and rendering two FloatingActionButtons to increment/decrement the counter.

counter_view.dart

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.

Barrel

Let's create lib/counter/counter.dart:

Add counter.dart to export all the public facing parts of the counter feature.

counter.dart

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.