Getting Started With the BLoC Pattern
See how to use the popular BLoC pattern to build your Flutter app architecture and manage the flow of data through your widgets using Dart streams. By Sardor Islomov.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Getting Started With the BLoC Pattern
25 mins
How to design the structure of an app is among the most heavily debated topics that arise in app development. Everyone seems to have their favorite architectural pattern with a fancy acronym.
iOS and Android developers are well versed in Model-View-Controller (MVC) and have used this pattern as a default choice when building apps. The model and view are separated, with the controller sending signals between them.
But Flutter brings a new, reactive style that’s not entirely compatible with MVC. A variation of this classical pattern has emerged from the Flutter community: BLoC.
BLoC stands for Business Logic Components. The gist of BLoC is that everything in the app should be represented as a stream of events: Widgets submit events, and other widgets will respond. BLoC sits in the middle, managing the conversation. Dart even comes with syntax for working with streams baked into the language!
The best part about this pattern is you won’t need to import any plugins or learn any custom syntax. Flutter already comes with everything you need.
In this tutorial, you’ll create an app to find articles using an API provided by raywenderlich.com. At the tutorial’s end, the app will do the following:
- Wrap API calls with the BLoC pattern
- Search for articles and show the results asynchronously
- Display detail of article
Getting Started
Download the starter project by clicking the Download Materials button and open it up with your favorite IDE. This tutorial will use Android Studio, but you can also use Visual Studio Code. Make sure to run flutter packages get
, either at the command line or when prompted by your IDE, to pull down the latest version of the HTTP package.
The starter project contains some basic models and networking files. When you open up the project it should look like this.
As you can see, rw_client.dart handles communicating with Raywenderlich servers. article.dart contains the Article
model class, which represents article objects from the API response.
You’ll learn more about the Raywenderlich API platform and network communication in the next section.
Raywenderlich API
The tutorial uses the Raywenderlich (RW) API to display a list of articles. You can check the data structure of the article model at raywenderlich.docs.apiary.io.
In this tutorial, you don’t need any setup to integrate RW API into the app. The tutorial already includes all necessary classes to work with RW API. The RWClient
class in rw_client.dart uses the http
library to make network requests. That is nothing complex.
Building the Application Architecture
When writing apps, whether using Flutter or another framework, it’s important to organize classes into layers. This is an informal convention; it’s not something concrete you can see in the code.
Each layer, or group of classes, handles one general task. The starter project comes with a folder called data. The data layer manages the app’s models and the connections to the back end; it knows nothing about the UI.
Every project is slightly different. But in general, you’ll want to build something like this:
This architectural contract is not too unlike classical MVC. The UI/Flutter layer can only talk to the BLoC layer. The BLoC layer receives input events, processes business logic using the data layer and responds with output events to the UI layers or other listeners. This structure can scale nicely as the app grows.
Anatomy of a BLoC
The BLoC Pattern is just an interface around Dart streams:
dart:async
provides an object called StreamController
. StreamControllers are manager objects that instantiate both a stream and a sink. A sink is the opposite of a stream. You add data to the StreamController
using Sink
and listen with the Stream
.
In the Bloc architecture, you use Stream
with Future
most of the time. dart:async
provides both of them. A Future
represents a potential value, or error, that will be available sometime in the future. Future
uses async
and await
keywords to perform asynchronous operations in Dart.
Future
tells you when the result is ready. A Stream
is a sequence of asynchronous events.
To summarize, BLoCs are objects that process and store business logic, use sinks to accept input and provide output via streams.
Enough theory. It’s time to build some screens with the appropriate BLoC.
Article List Screen
To search articles, you need to display a list of articles. In this section, you’ll create a simple screen with a search field at the top and a list view to show the results.
In the lib/ui folder of the project, create a file called article_list_screen.dart. Add a StatelessWidget
named ArticleListScreen
to the file:
class ArticleListScreen extends StatelessWidget {
const ArticleListScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// 1
return Scaffold(
appBar: AppBar(
title: const Text(
'Articles'
)
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(), hintText: 'Search ...'),
onChanged: (query) {
// 2
},
),
),
Expanded(
// 3
child:_buildResults(),
)
],
),
);
}
Widget _buildResults() {
return const Center(child: Text('No Results'));
}
}
The code above does the following:
- You create a screen with a
Scaffold
widget, which contains standard widgets such as:AppBar
,Column
andExpanded
. - The
TextField
widget triggers theonChange{}
method when the user types keywords. In the next sections of this tutorial, you’ll update theonChange{}
method to submit keywords to BLoC. -
_buildResults()
builds the list withArticle
objects. Right now, it shows only the message “No Results”. You’ll change it later in the tutorial.
If you build and run the app, it displays an empty, black screen. This is because main.dart doesn’t have a reference to ArticleListScreen
. Go to the ArticleFinder
class in main.dart and change the home:
property to return the new screen:
...
return MaterialApp(
title: 'RW Finder',
home: const ArticleListScreen(),
...
Build and run the app. It should look like this:
That’s better, but it still doesn’t do anything. It’s time to create some BLoCs!