Don’t do drugs, do Flutter! (talk #2)

Julio Henrique Bitencourt
Flutter Community
Published in
10 min readMar 7, 2019

This post was originally posted on blog.juliobitencourt.com and to a better experience is advised to go there, since medium is a little limited.

This post is a sequel from #1, so in any case just give it a look there.

In the previous one we dealt with a presentation ‘talk’ about Flutter SDK, and on this one we’ll see a detailed explanation of a live coding made to show a tech demo. The complete code is on my GitHub.

The app we’ll create is purposely very simple, although we’ll see some fun stuffs like http requests and screen navigation, besides getting the hands dirty and looking at some working Material Widgets. I’ll try to go step by step, as well as show the code and result.

App we’ll create.

But before getting the hands dirty it is important to understand as we already argued, in Flutter everything are Widgets and bla bla bla. However, there are two kinds of Widgets, Stateless and Statefull.

1> Stateless, are the ones who literally does not have state, they’re ‘static’, basically show info, as a Button, Text or Icon.

Button, text and icon are examples of Stateless Widgets

2> As for the Stateful, they have state, are dynamics, the user can somehow interact and change its state, as a checkbox wich is selected/not selected, or a slider.

Checkbox and sliders are example of Stateful Widgets

Now back to business, we’ll finally see the first code snippet.

This is as simple as a Flutter app can be, the main() method is responsible of starting the app, in our example it returns a function runApp() (yeah, for those who comes from java, how stunning is that?), from the material.dart package, that is responsible of receiving a Widget and basically throw it on the screen. Text is our first Widget, Stateless as mentioned before, basically receives a String and in this case a direction in wich we want to render the text. Flutter is completely compatible with LTR (Left to Right) and RTL(right to left), as the Arabic language.
The modifier => replaces the famous return {} . Running our app the result is:

Hello Flutter! Aligned at the top left

The text is rendered in LTR with a black background, yet very difficult to read at the corner of the screen, let’s use a simple widget Center:

Hello Flutter! Aligned at the center

The simple snippet above can show we don’t need a previous knowledge to understand that will be rendered a centered text. Flutter + Dart is a great combination to turn the code reading very intuitive. Even more after Dart 2 where new is no longer required. To give it a better looking we’ll extract what is inside runApp().

MyApp is our new Widget, Stateless because we don’t need to keep a state. Every widget has the build() method, very important to its lifecycle, called automatically by the framework every time it’s necessary to rebuild itself. Inside build() we return a MaterialApp, we can say it is a one-size-fits-all widget, having many functionalities to make it easy our life, as themes, navigation routes, among other things like the app title and the home parameter, where we defined our homepage as the text, only that this time without textDirection, since the MaterialApp already defines all it’s children to be LTR by default. But only that won’t change a thing in what our app looks like, that’s why we’ll introduce a new Widget.

We changed the homepage to a Scaffold, this one now is our one-size-fits-all widget for material design and one of its parameters is appBar, where we use an AppBar, who guess what? Defines an implementation of a Material Design AppBar.
With the TextStyle we’ll define a better look to the text, letting it blue with a font size 30.

Hello Flutter! Styled and aligned at the center

In this app we’ll fetch a people list with an http request that returns a json as response, this json is hospedated at the same repo on GitHub, here. The structure from json is very simple, essentially an object list with idPerson, name and urlImage.

Now in Dart, we can map to an object that represents our json.

Some key points on the code above.

  • The class Person has its attributes with it’s respective types as defined in json.
  • If we stop and think, any json structure is basically a key/value pair map. That’s why it is exactly this way that is represented in Dart. At line 8 we create a constructor fromJson responsible of deserializing the json, in other words, transforming it to an Object, that’s why it receives a Map of String ( the key will always be a String) and dynamic. Dynamic for Dart is like a generic type, any other type can be on a dynamic var.
  • We won’t use the toJson method, but is counts as knowledge as it’s responsible of ‘serializing’ the Object, in other words, transforming it to a Map/Json.

Now we’ll create a class called PeopleApi, responsible of making an http request, parse it and return a people list. And for that it will be necessary the http package from Dart. The Dart libs are hosted on pub.dartlang.com and in Flutter are managed through ubspec.yaml, so let’s add this dependency on it:

That will add the http package on our project.

The method _get() is the one who makes the request, and it’s with it we’ll learn a very important concept to Flutter. Dart is single thread, so whenever we want to execute a task that can take some time, like access a database or an http request, we need to do it asynchronously. Otherwise if we use the main thread the app would freeze and the user wouldn’t be able to interact with it anymore.

So, adding async on the method, we tell Dart that at any point in time our method will execute some task asynchronously, but when? Well, that’s why our friend await is for, as soon as Dart finds this keyword it thinks ‘Ok, from now on this will execute asynchronously, so I’ll just get back to my main thread’. And at this exact moment it will already return a result to whoever called the method at the first moment. What will it return? You may ask me.

A Future! Future is basically a promise, that is, some moment in the future (when the async method really finish the execution), this Future will have a concrete result.

On our get we use the _get() from http, imported from the package:http/http.dart package, in addition we define the await to make a request on the URL. After that, json from dart:convert to decode the body of the response, that defines as return a List of Map. That’s it! WITH TWO LINESSS OF CODE! We’ve made an http request and decoded the response.

In Dart, the character _ in front of the modifiers means that this var or method will be private.

The next step now is take the response of the request and transform it into our list of people, so let’s change PeopleApi.

Our method loadJsonFromApi(), async either, will basically use the _get() created previously, and for each Map of this list we’ll transform into a Person through the fromJson constructor, adding all into a list and returning it.
Let’s get back now to the fun part:

On the main file we extracted the Text to a new Widget PeopleWidget, this one is a little different from the previous one we created, it is a StatefulWidget, after all we’ll keep the state from our people on screen. Every Stateful widget must extend State, wich is the class responsible of literally manage the state. So let’s play with _PeopleWidgetState.

As we know, build() is called always that is necessary for the widget to rebuild itself, the truth is, in it’s lifecycle the build can be called many times, so it wouldn’t make sense to do a json request in it (imagine any time the user scrolls the list, a request is triggered). By the other hand, initState() is called only once on the widget creation, a very good candidate to make an API request. So when the widget is created, getPessoas() will be executed, making a call to the API, it is also async, so at any moment in the future it’ll fill our _people list. After this return, the setState() method will be called, this one is a specific method from Stateful widgets as is tells the widget to rebuild itself. (build() will be executed again). On the Text inside build() we have a ternary operator, if the people list is null (remember the json request is async, do the first time build is executed, _people will be null) we show ‘LOADING’ otherwise we print the people list. The result bellow:

Loading showing while people are not full loaded
List of people without toString()

Adding toString() on Person:

List of people with toString()

Still far from the final result, so let’s move on:

In case the request isn’t done yet, instead of ‘LOADING’ we change to CircularProgressIndicator that simply shows a circular loading. We also changed the print list to a ListView, widget that makes it easy the creation of horizontal and vertical lists, it has a builder where we pass the amount of widgets that will belong to the list, and with that, each will call on demand the function we defined on itemBuilderto return the widget corresponding to the index. By now we’ll only return a Text with the name of each person.

Circular loading

Now we have a list of names, but not with a very good look, so:

The ListTile already implements the Material Design specifications to sizes and spacing, and is an excelent candidate to use on our list, we’ll put the Texton its parameter title and the result will look much better:

With ListTile our list is looking much better

About the avatar image, we would also need to make a request, with all that async story and everything else, however, Flutter already gives us a ready to go implementation, all we need is an image URL and NetworkImage, then we use together with CircleAvatar to get the desired result, we also define in backgroundColor that while the image request are not done, it’ll show a blue background. Then we put all this inside leading ofListTile:

While the request isn’t done yet, a blue background is shown

The ideia now is to click in one of these people, navigate to a new details screen, for that we can create a file details.dart with a very new widget called DetailsPeople (Stateless, after all we won’t keep any state, only show person informations).

In this widget, we’ll receive the selected person via the constructor, on build we’ll use Scaffold again together with AppBar to have a MaterialDesign look and feel. On body we’ll introduce a new widget called Column, wich basically render its children Widgets one above the other, in our case, the avatar and name.
Now with this created, we can change on main.dart to call it.

We envelop the ListTile inside a GestureDetector, this will allow us to identify when the user will make a tap on it, and as a parameter of onTap we define the function that will be executed. With Navigatorand MaterialPageRoute we create a navigation route to the details page, push will basically put our new page on top, like a stack. The result will be a working navigation between the two pages.

Navigation between the screens

The widget Row works exactly as the Column, rendering the children widgets side by side. If we put our Column inside a Row we can align the widgets at horizontal with the help of MainAxisAlignment.center. And with that, if we put the Row inside a Container, it is possible to define a background color with Color.

Widgets aligned horizontally at center
Gray background

The result was not quite the expected, because we changed the background of everything, and we want to change only the background of the space occupied by the image and name. It happens that the Row by default occupies all the horizontal space available, allowing us to align everything at the center, and the Column does the same on vertical space, and one the Column is inside the Container, it ends up expanding too. To correct it, we can use the parameter mainAxisSize from Column with the mainAxisSize: MainAxisSize.min, now it will occupy only the minimum space required. We can take the chance and envelop our image inside Padding to a better spacing of our person’s space header, as well as increase the avatar radius and change the name with TextStyle.

Background color and avatar sizes adjusted
Styled name with TextStyle help

With that, we finally get the expected result done, although very simple we saw a lot of concepts and widgets that are useful and necessary to a real Flutter development, yet I will introduce a final modification, the frosting on the cake.

We added a new widget Perspective and the objective is not to see it in details (It is detailed explained on this article I used as base), but yet to show the power that Flutter gives to us developers on customizing (remember part #1?) what is rendered on canvas, after all, with a few lines of code changed, Isn’t it AWESOME?

Flutter Perspective!!! o/

That’s it, if you came to here and saw all the process, congratulations, hope I at least aroused your interest on the SDK, and you know, don’t do drugs, do Flutter!

--

--