You are on page 1of 18

6/21/2020 How to do Networking like a Pro in Flutter?

- The Startup - Medium

You have 1 free member-only story left this month. Sign up and get an extra one for free.

Listen to this article Powered by Play.ht

Converting to audio ....

How to do Networking like a Pro in Flutter?


Learn how to do Networking in Flutter Fast and do it right keeping your Code and Application
Architecture Clean

Dhananjay Trivedi
Apr 25 · 7 min read

When I started learning Networking for the first time in Android there was a lot of
things involved like

Calling the networking functions asynchronously


https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 1/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

Adding some Networking library like Volley or Retrofit or write some more
boilerplate code with the Http

Parsing data manually or with some external library like GSON

Finally updating your the main UI thread, asynchronously.

It was painful.

While Flutter simplifies a lot of development work as compared to developing the


native application you can certainly expect it to simplify this whole process by a lot as
well!

Let’s see how.

Also, I will try to teach you networking while also


keeping your Code Clean! So that you can do
Networking in Flutter like a PRO-BOSS!
. . .

Before we get started, Make sure:

You know about Stateful and Stateless Widget.

You know about async and await keyword in dart.

A little bit about State Management using Provider Package. [Quick Read]

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 2/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

Add the following dependencies.

dev_dependencies:
flutter_test:
sdk: flutter
http: ^0.12.0+4
provider_architecture: ^1.0.5

Part 1 : Networking for Beginners


(The example code doesn’t follow the best practices and is for demonstration purposes only,
we will make it Clean as we progress)

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 3/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

1. Get your API Response Data


We will be building the app to get the latest data from this API which returns JSON
Data as response. But you can choose any API you want and follow along.

Copy the JSON Response to your clipboard.

2. Let’s create our Data Model Class.


For this visit Json to Dart Converter. This is super cool 😍 makes life so much easy!

JSON to Dart
Paste your JSON in the textarea below, click convert and get your Dart classes for free.

javiercbk.github.io

Paste your Json Data in the Left field and give name of your Model Class in the field
below. I have given APIResponseModel

Hit generate Dart and copy the dart code to clipboard.

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 4/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

Back in your project, create a new Dart file and give it a name, I have given
api_response_mode.dart and copy paste your Dart Code.

3. Let’s Create the UI

This is the starter code for this UI. Make sure you call HomeScreen() from your

main.dart .

1 import 'dart:convert';
2
3 import 'package:flutter/cupertino.dart';
4 import 'package:flutter/material.dart';
5 import 'package:http/http.dart' as http;
6
https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 5/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium
6
7 import 'api_response_model.dart';
8
9 class HomeScreen extends StatefulWidget {
10 @override
11 _HomeScreenState createState() => _HomeScreenState();
12 }
13
14 class _HomeScreenState extends State<HomeScreen> {
15 APIResponseModel apiResponseModel;
16 bool isLoading = false;
17
18 @override
19 Widget build(BuildContext context) {
20 return Container(
21 color: Colors.white,
22 child: SafeArea(
23 child: Scaffold(
24 appBar: AppBar(
25 title: Text("Networking Example"),
26 ),
27 body: Container(child: Center(child: buildDataWidget())),
28 floatingActionButton: FloatingActionButton(
29 child: isLoading
30 ? CircularProgressIndicator(
31 backgroundColor: Colors.white,
32 )
33 : Icon(Icons.cloud_download),
34 tooltip: "Get Data from API",
35 onPressed: () => getDataFromAPI(),
36 ),
37 )));
38 }
39
40 void getDataFromAPI() async {
41 setState(() {
42 isLoading = true;
43 });
44 const String API_URL = "https://corona.lmao.ninja/v2/all";
45 var response = await http.get(Uri.parse(API_URL));
46 var parsedJson = await json.decode(response.body);
47 setState(() {
48 apiResponseModel = APIResponseModel.fromJson(parsedJson);
49 isLoading = false;
50 });
51 }
52
53 buildDataWidget() {
https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 6/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

54 if (apiResponseModel == null)
55 return Container(
56 child: Padding(
57 padding: const EdgeInsets.all(16.0),
58 child: Text(
59 "Press the floating action button to get data",
60 style: TextStyle(fontSize: 24),
61 textAlign: TextAlign.center,
62 ),
63 ),
64 );
65 else {
66 return Text(
67 "Total Cases : ${apiResponseModel.cases}\n"
68 "Today's Cases : ${apiResponseModel.todayCases}\n"
69 "Total Deaths : ${apiResponseModel.deaths}\n"
70 "Today's Deaths : ${apiResponseModel.todayDeaths}\n"
71 "Total Recovered : ${apiResponseModel.recovered}\n"
72 "Active Cases : ${apiResponseModel.active}\n"
73 "Critical Cases : ${apiResponseModel.critical}\n"
74 "Cases per million: ${apiResponseModel.casesPerOneMillion}\n"
75 "Deaths per million: ${apiResponseModel.deathsPerOneMillion}\n"
76 "Total Tests Done: ${apiResponseModel.tests}\n"
77 "Tests per million: ${apiResponseModel.testsPerOneMillion}\n"
78 "Affected countires : ${apiResponseModel.affectedCountries}\n",
79 style: TextStyle(fontSize: 18),
80 );
81 }
82 }

4. Let’s do some networking.


On press of the floating action button we will call the method getDataFromApi()

which is defined as shown below.

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 7/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

setState will rebuild the widget with updated apiResponseModel data object. So we
can use it’s value inside our Text widget to show information which is inside
buildDataWidget()

But in beginning apiResponseModel will be null, which will make our app crash.
Hence, we need to check

if(apiResponseModel == null)
return Text("Default Text");
else
return Text("The data values");

Hence our updated buildDataWidget() function looks like:

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 8/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

That’s it!

Here is the complete code in action so far. I have added a Progress bar as well, to
make it a little better 😇

Please note : I have not taken care of error cases from the API or
some exception handling during the networking in parsing.

Moving one step ahead as a Professional Developer 🤘


In the above solution, our HomeScreen() widget was taking care of

Displaying the data to the user

Taking user action of onPressed

Doing the networking

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 9/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

Parsing the data

Updating the state of the UI

And the code isn’t very complex as well. But as the app complexity increases, the
number of functions and the number of setState() will only increase over time
making your code:

Harder to maintain

Harder to change

Decrease in performance of your application

Decrease in your productivity to add new features

There are a set of principles called SOLID Principles which can help you design better
application architecture.

Here is a link if you want to go through them quickly.

The SOLID Principles for good software design


Every software developer must know them
medium.com

One of the most popular rule is the Single Responsibility Principle which encourages
you to minimize the amount of responsibility a function / class as to 1.

We will try to minimize the responsibility of our UI, ie, HomeScreen with a better
design.

Let’s first understand a basic Clean Architecture.


A basic rule for Clean Architecture is to aim for minimising the responsibility of each
module or class.

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 10/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

1 The UI or

Taking User Input


HomeScreen will now be only responsible for

Displaying data to the user

2 The ViewModel will be responsible for

Managing the State of the UI.

Taking care of the events triggered from the UI.

The data for the UI will be stored inside the ViewModel, and as the ViewModel data
updates, the UI will also rebuild itself accordingly to show the latest data in the view
model.

3 The Repository as the name suggests is responsible for

Managing data for the ViewModel from different sources.

Remember, ViewModel is only responsible for storing the data and doesn’t care
where the data is coming from. ViewModel just gets the data and stores it in the
ViewModel.

In our current example, data is coming only from one source that is the API. But when
you will be building even a bit complex app, you might be dealing with multiple data
sources like OfflineCache, Offline Database, FileStorage.

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 11/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

You shouldn’t expect your ViewModel to call and delegate each one of these, your
repository will be managing the data from these different sources for your ViewModel.

If in future, you want to swap an OfflineCaching system with a database, you only will
have to make the updates in your Repository class without having to touch your UI or
ViewModel.

4 Separate Repositories will be setup for each of the data sources of your
application.

Each repository will be responsible for managing data from each source. For example
NetworkRepository will contain code for Networking through http while there will be
a separate FirebaseRepo for managing your Firebase related logic. If you have offline
caching, you will create a repo for that as well. I hope you get the picture.

Pro Tip:

There will be scenarios where you will have to pass or return


multiple parameters to and from a function. Create a Model for those
cases try to group the similar parameters and wrap them into one
model.

This helps you in easily changing the number of parameters in the


future.

This also helps improves the testability of each functions.

. . .

Let’s finally Clean that Code Up!


I will be using ViewModel from Flutter Provider Package.

1. First thing you have to do is to remove the two state fields from the HomeScreen()
Widget.

2. Then, Create your ViewModel and add those two fields inside the viewmodel.

1 import 'package:flutter/cupertino.dart';
2 import 'package:networking_like_a_boss/model/networking_response.dart';
3 import 'package:networking_like_a_boss/screens/home/home_repository.dart';
https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 12/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

4 import '../../model/api_response_model.dart';
5
6 class HomeScreenViewModel extends ChangeNotifier {
7 HomeScreenViewModel() {
8 /// As soon as VM initializes
9 /// We want to get the latest data
10 getDataFromAPI();
11 }
12
13 APIResponseModel apiResponseModel;
14 String messageToShow = "";
15 bool isLoading = false;
16
17 void getDataFromAPI() async {
18 /// Start showing the loader
19 isLoading = true;
20 notifyListeners();
21
22 /// Wait for response
23 NetworkingResponse networkingResponse =
24 await HomeScreenRepository().getLatestStatsData();
25
26 /// We check the type of response and update the required field
27 if (networkingResponse is NetworkingResponseData) {
28 /// Updating the APIResponseModel when success
29 apiResponseModel = networkingResponse.apiResponseModel;
30 } else if (networkingResponse is NetworkingException) {
31 /// Updating the errorMessage when fails
32 messageToShow = networkingResponse.message;
33 }
34
35 /// Stop the loader
36 isLoading = false;
37 notifyListeners();
38 }
39 }

3. Setup HomeScreenRepository Class

1 import 'package:networking_like_a_boss/model/api_response_model.dart';
2 import 'package:networking_like_a_boss/model/networking_response.dart';
3 import 'package:networking_like_a_boss/repo/network_repo/NetworkRepo.dart';
4
5 class HomeScreenRepository {
6 /// ViewModel calls its Repository to getLatestStatsData
7 /// The Repository will take care of getting the data from thr right source
https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 13/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

8 /// Only HomeRepository knows that it has to call NetworkRepo()


9 /// ViewModel doesn't care if its coming from API or Offline Cache
10
11 Future<NetworkingResponse> getLatestStatsData() {
12 return NetworkRepo().getLatestDataFromAPI();
13 }
14 }

home_repository.dart hosted with ❤ by GitHub view raw

4. Add NetworkRepo Class , also, earlier we didn’t took care for Exception Handling. We
will do that now in a Cleaner way!

1 import 'dart:convert';
2
3 import 'package:http/http.dart' as http;
4 import 'package:networking_like_a_boss/model/api_response_model.dart';
5 import 'package:networking_like_a_boss/model/networking_response.dart';
6 import 'package:networking_like_a_boss/utils/constants.dart';
7
8 /// Network Repo will do the networking for you
9 /// And will also take care of parsing
10 /// and exception handling
11 /// will simply return you data model or the exception message
12
13 class NetworkRepo {
14
15 /// Instead of returning ApiResponseModel
16 /// We have created a parent class called NetworkingResponse
17 /// Which takes care of Successful and Failed response
18 /// So we either send a successful or failed response wrapped in NetworkingResponse
19
20 Future<NetworkingResponse> getLatestDataFromAPI() async {
21 try {
22 var response = await http.get(Uri.parse(API_END_POINT_URL));
23 var parsedJson = await json.decode(response.body);
24 APIResponseModel apiResponseModel = APIResponseModel.fromJson(parsedJson);
25 return NetworkingResponseData(apiResponseModel);
26 } catch (exception) {
27 return NetworkingException(exception.toString());
28 }
29 }
30 }

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 14/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

5. Finally just add the setup the ViewModel Provider and listen to the required fields in
the HomeScreen Widget.

As soon as the app starts, the HomeScreen ViewModel get initialized and the app get’s
latest data for the user without having to click on the button.

1 import 'package:flutter/cupertino.dart';
2 import 'package:flutter/material.dart';
3 import 'package:networking_like_a_boss/screens/home/home_screen_view_model.dart';
4 import 'package:provider_architecture/provider_architecture.dart';
5
6 import '../../model/api_response_model.dart';
7
8 class HomeScreen extends StatelessWidget {
9 @override
10 Widget build(BuildContext context) {
11 return ViewModelProvider<HomeScreenViewModel>.withConsumer(
12 viewModel: HomeScreenViewModel(),
13 builder: (context, viewModel, child) {
14 return Container(
15 color: Colors.white,
16 child: SafeArea(
17 child: Scaffold(
18 appBar: buildAppBar(),
19 body: buildBody(viewModel),
20 floatingActionButton: buildFloatingActionButton(viewModel),
21 )));
22 });
23 }
24
25 AppBar buildAppBar() {
26 return AppBar(
27 title: Text("Networking Like a Pro"),
28 );
29 }
30
31 Widget buildBody(viewModel) {
32 /// building our UI
33 /// notice we are observing viewModel.apiResponseModel
34 /// Hence buildDataWidget will rebuild when apiResponse changes in ViewModel
35 return Container(child: Center(child: buildDataWidget(viewModel)));
36 }
37
38 FloatingActionButton buildFloatingActionButton(viewModel) {
39 return FloatingActionButton(
40 child: viewModel.isLoading
https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 15/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

41 ? CircularProgressIndicator(
42 backgroundColor: Colors.white,
43 )
44 : Icon(Icons.cloud_download),
45 tooltip: "Get Data from API",
46
47 /// Calling our viewModel function
48 onPressed: () => viewModel.getDataFromAPI(),
49 );
50 }
51
52 buildDataWidget(viewModel) {
53 APIResponseModel apiResponseModel = viewModel.apiResponseModel;
54
55 if (apiResponseModel == null)
56 return Container(
57 child: Padding(
58 padding: const EdgeInsets.all(16.0),
59 child: Text(
60 "${viewModel.messageToShow}",
61 style: TextStyle(fontSize: 24),
62 textAlign: TextAlign.center,
63 ),
64 ),
65 );
66 else {
67 return Text(
68 "Total Cases : ${apiResponseModel.cases}\n"
69 "Today's Cases : ${apiResponseModel.todayCases}\n"
70 "Total Deaths : ${apiResponseModel.deaths}\n"
71 "Today's Deaths : ${apiResponseModel.todayDeaths}\n"
72 "Total Recovered : ${apiResponseModel.recovered}\n"
73 "Active Cases : ${apiResponseModel.active}\n"
74 "Critical Cases : ${apiResponseModel.critical}\n"
75 "Cases per million: ${apiResponseModel.casesPerOneMillion}\n"
76 "Deaths per million: ${apiResponseModel.deathsPerOneMillion}\n"
77 "Total Tests Done: ${apiResponseModel.tests}\n"
78 "Affected countires : ${apiResponseModel.affectedCountries}\n",
79 style: TextStyle(fontSize: 18),
80 );
81 }
82 }

6. Also, I like to structure my all these files like this:

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 16/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

I create a screens package and inside I group each screen with its UI, ViewModel
and Repo inside one package only.

For example ui >> home >> contains all three files.

repo contains the data source repositories and not the screen repositories.

Again, there is no hard and fast rule to structure your project this way. It’s just what I
prefer for this project.

Try running the app! Things should still be


“working” same as before but now you have code
written by a professional coder 😉
Here is the full project repository:

devDeejay/FlutterNetworkingLikeABoss
You can't perform that action at this time. You signed in with another tab or
window. You signed out in another tab or…

github.com
https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 17/18
6/21/2020 How to do Networking like a Pro in Flutter? - The Startup - Medium

. . .

I would love to hear more from you, please reach out if you have any ideas for
improvements, feedback or suggestions.

Flutter Programming Clean Code Mobile App Development Android

About Help Legal

Get the Medium app

https://medium.com/swlh/how-to-do-networking-like-a-pro-in-flutter-7e2612103cb5 18/18

You might also like