0% found this document useful (1 vote)
118 views

Architect Your Flutter Project Using BLOC Pattern - FlutterPub - Medium

The document is an article that discusses architecting Flutter projects using the BLOC pattern. It introduces the BLOC pattern and shows how to structure a Flutter project using BLOC. The article sets up a sample project to fetch popular movie data from an API and displays it in a grid view. It creates packages and files for blocs, models, resources and UI components to divide the project structure based on the BLOC architecture.

Uploaded by

Siddharth Yadav
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (1 vote)
118 views

Architect Your Flutter Project Using BLOC Pattern - FlutterPub - Medium

The document is an article that discusses architecting Flutter projects using the BLOC pattern. It introduces the BLOC pattern and shows how to structure a Flutter project using BLOC. The article sets up a sample project to fetch popular movie data from an API and displays it in a grid view. It creates packages and files for blocs, models, resources and UI components to divide the project structure based on the BLOC architecture.

Uploaded by

Siddharth Yadav
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

Architect your Flutter project using BLOC pattern


Sagar Suri
Aug 26, 2018 · 11 min read

Hi Folks! I am back with another brand new article on Flutter. This time I will be
talking and demonstrating to you “how to architect your Flutter projects”. So that you
can maintain, scale and test your Flutter projects easily. Before diving into the actual
topic. I would like to share a small story on why we should focus on building a solid
architect of our projects.

Update: Part 2 and Part 3 of this article has be published with some changes in the current
design to address some issues and to showcase some amazing implementations. Here is the
link.

Part 3

Compile time Dependency Injection in Flutter


Hey Folks! I am back with another brand new article on Flutter. This time I
will be covering a very interesting and…
blog.usejournal.com

Part 4

Integration and Unit testing in Flutter


Make your app’s features bullet-proof by testing them
medium.com

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 1/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

Why do you need to architect your project?


“Once upon a time in the year 2015. I was a novice competitive
programmer(Hackerearth profile) and was also learning android app development. As
a competitive programmer, I only cared about the output and efficiency of the program
I wrote. I never gave a second thought to structuring my programs or projects I wrote.
This trend and style reflected in my android projects as well. I was writing android apps
with a competitive programmer’s mindset. At the beginning when I was working on my
own projects it was all good as I never had a boss or manager who can give me
requirements to add new features or change existing features in the app. But when I
started working in a startup and building Android apps for them. I always took a lot of
time to change an existing feature in the app. Not only that, I even added bugs as an
add-on feature in the process of building the app. The main root cause of all these
problems was, “I never followed any architectural pattern or never structured my
projects”. As time passed and I started understanding the world of software, I
transitioned myself from a competitive programmer to a software engineer. Today
whenever I start a new project my primary focus is to build a solid structure or
architecture of the project. That helped me to be a better and stress-free software
engineer 😄.”

Putting an end to my boring story 😅. Let’s start working on the main goal of this
article. “Architect your Flutter projects using BLOC pattern”.

Our Goal
I will be building a very simple app. It will have one screen where you can see a grid list
of items. Those items will be fetched from the server. The list of items will be popular
movies from The Movies DB site.

Note: Before moving any further I assume you understand Widgets, how to make a
network call in Flutter and have intermediate knowledge in Dart. This article will be a
little lengthy and heavily hyperlinked to other resources so that you can read further on
specific topics.

So let’s begin the show. 😍


Before diving directly into the code. Let me give you a visual experience of the
architecture we will be following to structure this app.

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 2/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

The BLOC pattern

The above diagram shows how the data flow from UI to the Data layer and vice versa.
BLOC will never have any reference of the Widgets in the UI Screen. The UI screen will
only observe changes coming from BLOC class. Let’s have a small Q&A to understand
this diagram:

1. What is BLOC Pattern?

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 3/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

Its a state management system for Flutter recommended by Google developers. It helps
in managing state and make access to data from a central place in your project.

. . .

2. Can I co-relate this architecture with any other architectures out


there?
Yes of course. MVP and MVVM are some good examples. Only the thing that will
change is: BLOC will be replaced with ViewModel in MVVM.

. . .

3. What is under the hood of BLOC ? or What is that core thing that
manages the state in one place?
STREAMS or REACTIVE approach. In general terms, data will be flowing from the
BLOC to the UI or from UI to the BLOC in the form of streams. If you have never heard
about streams. Read this Stack Overflow answer.

. . .

Hope this small Q&A section cleared some of your doubts. If you need further clarity or
want to ask a specific question, you can comment down below or connect directly with
me at LinkedIn.

Let’s start building the project with BLOC pattern

1. First create a new project and clear all the code in the main.dart file. Type below
command in your terminal:

flutter create myProjectName

2. Write down the below code in your main.dart file:

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 4/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

import 'package:flutter/material.dart';
import 'src/app.dart';

void main(){
runApp(App());
}

You must be getting an error in the second line. We will solve it in the upcoming steps.

3. Create a src package under the lib package. Inside src package create a file and name it
as app.dart. Copy paste the below code inside the app.dart file.

import 'package:flutter/material.dart';
import 'ui/movie_list.dart';

class App extends StatelessWidget {


@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
theme: ThemeData.dark(),
home: Scaffold(
body: MovieList(),
),
);
}
}

4. Create a new package inside the src package and name it as resources.

Now create few new packages i.e blocs, models, resources and ui as shown in the below
diagram and then we are set with the skeleton of the project:

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 5/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

Project structure

blocs package will hold our BLOC implementation related files. models package will
hold the POJO class or the model class of the JSON response we will be getting from
the server. resources package will hold the repository class and the network call
implemented class. ui package will hold our screens that will be visible to the user.

5. One last thing we have to add i.e RxDart a third party library. Open your
pubspec.yaml file and add rxdart: ^0.18.0 as shown below:

dependencies:
flutter:
sdk: flutter

# The following adds the Cupertino Icons font to your application.


# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
rxdart: ^0.18.0
http: ^0.12.0+1

sync your project or type below command in terminal. Make sure you execute this
command inside your project directory.

flutter packages get

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 6/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

6. Now we are complete with the skeleton of the project. Time to deal with the most bottom
layer of the project i.e the network layer. Let’s understand the API end point which we are
going to consume. Hit this link and you will be taken to the movie database API site. Sign
up and get your API key from the Settings page. We will be hitting the below url to get the
response:

http://api.themoviedb.org/3/movie/popular?api_key=“your_api_key”

Put your API key in the above link and hit(Remove double quotes as well). You can see
the JSON response something like this:

{
"page": 1,
"total_results": 19772,
"total_pages": 989,
"results": [
{
"vote_count": 6503,
"id": 299536,
"video": false,
"vote_average": 8.3,
"title": "Avengers: Infinity War",
"popularity": 350.154,
"poster_path": "\/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg",
"original_language": "en",
"original_title": "Avengers: Infinity War",
"genre_ids": [
12,
878,
14,
28
],
"backdrop_path": "\/bOGkgRGdhrBYJSLpXaxhXVstddV.jpg",
"adult": false,
"overview": "As the Avengers and their allies have continued
to protect the world from threats too large for any one hero to
handle, a new danger has emerged from the cosmic shadows: Thanos. A
despot of intergalactic infamy, his goal is to collect all six
Infinity Stones, artifacts of unimaginable power, and use them to
inflict his twisted will on all of reality. Everything the Avengers
have fought for has led up to this moment - the fate of Earth and
existence itself has never been more uncertain.",
"release_date": "2018-04-25"
},

7. Let’s build a model or POJO class for this type of response. Create a new file inside the
models package and name it as item_model.dart. Copy and paste the below code inside
item_model.dart file:
https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 7/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

class ItemModel {
int _page;
int _total_results;
int _total_pages;
List<_Result> _results = [];

ItemModel.fromJson(Map<String, dynamic> parsedJson) {


print(parsedJson['results'].length);
_page = parsedJson['page'];
_total_results = parsedJson['total_results'];
_total_pages = parsedJson['total_pages'];
List<_Result> temp = [];
for (int i = 0; i < parsedJson['results'].length; i++) {
_Result result = _Result(parsedJson['results'][i]);
temp.add(result);
}
_results = temp;
}

List<_Result> get results => _results;

int get total_pages => _total_pages;

int get total_results => _total_results;

int get page => _page;


}

class _Result {
int _vote_count;
int _id;
bool _video;
var _vote_average;
String _title;
double _popularity;
String _poster_path;
String _original_language;
String _original_title;
List<int> _genre_ids = [];
String _backdrop_path;
bool _adult;
String _overview;
String _release_date;

_Result(result) {
_vote_count = result['vote_count'];
_id = result['id'];
_video = result['video'];
_vote_average = result['vote_average'];
_title = result['title'];
_popularity = result['popularity'];
_poster_path = result['poster_path'];
_original_language = result['original_language'];
_original_title = result['original_title'];
for (int i = 0; i < result['genre_ids'].length; i++) {
_genre_ids.add(result['genre_ids'][i]);
}
https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 8/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

_backdrop_path = result['backdrop_path'];
_adult = result['adult'];
_overview = result['overview'];
_release_date = result['release_date'];
}

String get release_date => _release_date;

String get overview => _overview;

bool get adult => _adult;

String get backdrop_path => _backdrop_path;

List<int> get genre_ids => _genre_ids;

String get original_title => _original_title;

String get original_language => _original_language;

String get poster_path => _poster_path;

double get popularity => _popularity;

String get title => _title;

double get vote_average => _vote_average;

bool get video => _video;

int get id => _id;

int get vote_count => _vote_count;


}

I hope you can map this file with the JSON response. If not, we are mostly interested in
the poster_path inside the Results class that’s what you need to know to move further.
We will display all the posters of popular movies in our main UI. fromJson() method is
just getting the decoded JSON and putting the values in the correct variables.

8. Now its time to work on the network implementation. Create a file inside the resources
package and name it as movie_api_provider.dart. Copy and paste the below code inside
the file and I will explain it to you:

import 'dart:async';
import 'package:http/http.dart' show Client;
import 'dart:convert';
import '../models/item_model.dart';

class MovieApiProvider {

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 9/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

Client client = Client();


final _apiKey = 'your_api_key';

Future<ItemModel> fetchMovieList() async {


print("entered");
final response = await client
.get("http://api.themoviedb.org/3/movie/popular?
api_key=$_apiKey");
print(response.body.toString());
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
return ItemModel.fromJson(json.decode(response.body));
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
}

Note: Please put your API key in the variable _apiKey inside the
movie_api_provider.dart file or else it won’t work.

fetchMovieList() method is making the network call to the API. Once the network call
is complete it’s returning a Future ItemModel object if the network call was successful
or it will throw an Exception.

9. Next we are going to create a new file inside the resources package and name it as
repository.dart. Copy and paste the below code inside the file:

import 'dart:async';
import 'movie_api_provider.dart';
import '../models/item_model.dart';

class Repository {
final moviesApiProvider = MovieApiProvider();

Future<ItemModel> fetchAllMovies() =>


moviesApiProvider.fetchMovieList();
}

We are importing the movie_api_provider.dart file and calling its fetchMovieList()

method. This Repository class is the central point from where the data will flow to the
BLOC.

10. Now comes a little complicated part. Implementing the bloc logic. Let’s create a new file
inside the blocs package and name it as movies_bloc.dart. Copy paste below code and I
https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 10/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

will explain you the code in little detail:

import '../resources/repository.dart';
import 'package:rxdart/rxdart.dart';
import '../models/item_model.dart';

class MoviesBloc {
final _repository = Repository();
final _moviesFetcher = PublishSubject<ItemModel>();

Observable<ItemModel> get allMovies => _moviesFetcher.stream;

fetchAllMovies() async {
ItemModel itemModel = await _repository.fetchAllMovies();
_moviesFetcher.sink.add(itemModel);
}

dispose() {
_moviesFetcher.close();
}
}

final bloc = MoviesBloc();

We are importing a package import ‘package:rxdart/rxdart.dart’; which will


eventually import all the RxDart related methods and classes in this file. Inside the
MoviesBloc class, we are creating the Repository class object which will be used to
access the fetchAllMovies() . We are creating a PublishSubject object whose

responsibility is to add the data which it got from the server in the form of ItemModel
object and pass it to the UI screen as a stream. To pass the ItemModel object as stream
we have created another method allMovies() whose return type is Observable(watch
this video if you don’t understand Observables). If you see the last line we are creating
the bloc object. This way we are giving access to a single instance of the MoviesBloc
class to the UI screen.

If you don’t know what reactive programming is. Please read this simple explanation.
In simple words, whenever there is new data coming from the server. We have to
update the UI screen. To make this updating task simple we are telling the UI screen to
keep observing any change coming from the MoviesBloc class and accordingly update
your content. This “observing” of new data can be done using RxDart.

11. Now the last section. Create a new file inside the ui package and name it as
movie_list.dart. Copy paste the below code:

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 11/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

import 'package:flutter/material.dart';
import '../models/item_model.dart';
import '../blocs/movies_bloc.dart';

class MovieList extends StatelessWidget {


@override
Widget build(BuildContext context) {
bloc.fetchAllMovies();
return Scaffold(
appBar: AppBar(
title: Text('Popular Movies'),
),
body: StreamBuilder(
stream: bloc.allMovies,
builder: (context, AsyncSnapshot<ItemModel> snapshot) {
if (snapshot.hasData) {
return buildList(snapshot);
} else if (snapshot.hasError) {
return Text(snapshot.error.toString());
}
return Center(child: CircularProgressIndicator());
},
),
);
}

Widget buildList(AsyncSnapshot<ItemModel> snapshot) {


return GridView.builder(
itemCount: snapshot.data.results.length,
gridDelegate:
new
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
return Image.network(
'https://image.tmdb.org/t/p/w185${snapshot.data
.results[index].poster_path}',
fit: BoxFit.cover,
);
});
}
}

Best and interesting part of this class is, I am not


using a StatefulWidget. But instead I am using a
StreamBuilder which will do the same job what
StatefulWidget does i.e updating the UI.

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 12/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

One thing to point here, that I am making a network call inside the build method which
should not be done as build(context) a method can be called multiple times. I will be
updating this article with a better approach. But for now, as the article is getting big
and complicated I am keeping things simple i.e making the network call inside the
build(context) method.

As I told you, our MoviesBloc class is passing the new data as a stream. So to deal with
streams we have a nice inbuilt class i.e StreamBuilder which will listen to the incoming
streams and update the UI accordingly. StreamBuilder is expecting a stream parameter
where we are passing the MovieBloc’s allMovies() method as it is returning a stream.
So the moment there is a stream of data coming, StreamBuilder will re-render the
widget with the latest data. Here the snapshot data is holding the ItemModel object.
Now you can you any Widget to display whatever is there in the object(Here your
creativity comes into the picture). I used a GridView to display all the posters that are
there in the results list of ItemModel object. This is the output of the final product:

Popular Movies Flutter Demo

Small demo. The video was not capturing the complete frames I guess 😐

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 13/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

So we have hit the end of this article. Great job folks for holding on till the end. Hope
you like this article. If you have any doubts or questions do connect with me at
LinkedIn or Twitter. Do appreciate the article with some claps and comments.

If you want the complete code. Here is the github repository of the project.

Check out my other articles

E ective BLoC pattern


Hey Folks, Its been so long I have written anything about Flutter. After
writing two articles on BLoC pattern I was…

medium.com

When Firebase meets BLoC Pattern


Hi Flutterian! I am back with another brand new article. This time I am
excited to show you all how I integrated some…
medium.com

. . .

The Flutter Pub is a medium publication to bring you the latest and amazing resources
such as articles, videos, codes, podcasts etc. about this great technology to teach you
how to build beautiful apps with it. You can find us on Facebook, Twitter, and Medium
or learn more about us here. We’d love to connect! And if you are a writer interested in
writing for us, then you can do so through these guidelines.

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 14/15
07/02/2020 Architect your Flutter project using BLOC pattern - FlutterPub - Medium

Android Flutter Software Architecture iOS Rxdart

About Help Legal

https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1 15/15

You might also like