Getting Started With Flutter: Part Three

2020-08-10

This is part three of a series of blog posts about getting started with Flutter. In part two, we used the Flutter plugin to create a new app project, ran the app using an Android Emulator and made use of Flutters’ Hot Reload feature

In this third and final post. You’ll change your flutter app into a joke app. The jokes are retrieved from an API and rendered onscreen.

Adding dependencies to your app

With your new project open in Android Studio. Open the pubspec.yaml file.

Welcome screen with create a new flutter project option

The pubspec file is a place to store metadata about your project. It’s also the place where app dependencies are declared. If you were writing a Flutter package, a library for other developers to use, this is the place where you describe what your package does to other developers.

For now, you’re going to add a package called http. It’s a package for making http requests using Dart. In the pubspec, find the dependencies section and update it to look like the following:

dependencies:
  flutter:
    sdk: flutter
  http: ^0.12.2

Next, tap the Pub Get button running along the top of the pubspec.

Welcome screen with create a new flutter project option

A window will appear along the bottom of Android Studio, showing the pub get command being run. Once it completes, the http package is downloaded and available to use in your app.

If you want to know more about what packages are available for use with Flutter, there’s a dedicated site called pub.dev where you can search for them. You can also publish your own packages here. We won’t cover publishing packages here.

With the http package added, the next thing to do is to use it in a dart class.

Creating a Dart File

In Android Studio, create a new dart class in the main folder. You can do that by right clicking on the folder, then moving your cursor over new, then finally clicking Dart File that appears in the popup.

Create a new dart file

A popup will appear, asking for the name of your new dart file. Call it jokes, then hit enter. A new window will appear, containing an empty dart file.

An empty dart file

At the top of the file, add the following lines to import the http package and another package called Convert. Convert is a builtin package for dart, providing encoders and decoders for different types of data formats. We’ll use Convert to retrieve a joke out of the json response returned by the API.

import 'dart:convert' as convert;
import 'package:http/http.dart' as http;

Next, add the following code to add a class and a method to the file:

// 1
class Jokes {
  // 2
  Future<String> getJoke() async {
    // 3
    final response = await http.get(
        'https://sv443.net/jokeapi/v2/joke/Programming');

    // 4
    if (response.statusCode == 200) {
      var json = convert.jsonDecode(response.body);
      return json['joke'];
    // 5
    } else {
      throw Exception('Failed to load joke');
    }
  }
}

Here’s what the dart code does:

  1. You declare a class called Jokes. Dart is similar to other languages, in that it uses class and object oriented programming

  2. You declare a method called getJoke(). The method returns a Future of type String. A Future is an object used to deal with code that takes time to return a value. Think of it as the method promising to return a value once it knows what the value is. The async keyword after the method is used by dart to know when a method won’t return a value straight away. You’ll see why this is important soon.

  3. You use http.get() to retrieve a joke from an API and store the result in response. The await keyword is used because this method can take time to return get the response and return a value. Await tells dart to wait for the result of the API request before executing the code below it.

  4. Once the API request is retrieved. You check to see if the request contains a 200 status code. If it is, all is well and you use convert to parse out and return the joke from the json response.

  5. If the response code is anything other than 200, something unexpected happened with the request. If this happens, an exception is thrown.

With the API hooked up. The final part is to update the UI to use the Joke class and show the joke.

Updating the UI

Open main.dart. Then scroll down to the _MyHomePageState class. This class is responsible for updating the state of the screen. At the moment, it only knows the amount of times the button has been clicked.

Update the class so it instead retrieves a joke, then renders it to the screen.

class _MyHomePageState extends State<MyHomePage> {

  // 1
  Jokes _jokes = Jokes();

  // 2
  String _joke = "";

  // 3
  void _getJoke() async {

    // 4
    var joke = await _jokes.getJoke();

    // 5
    setState(() {

      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      // 6
      _joke = joke;
    });
  }

Here’s what the code is doing.

  1. You declare an instance variable called _jokes, assigning it the Jokes class created earlier.

  2. You rename the _counters variable to _joke, then give it an empty string as a default value.

  3. You rename the method to _getJoke, then add the async keyword to show this method relies on code that can take some time to return.

  4. You call the getJoke() method you created earlier to retrieve a joke from the API. The await keyword is used here because you declared getJoke() as async earlier. This tells Dart to wait for the joke to be returned before proceeding.

  5. The setState() method is called. This tells Flutter the UI is being updated and should rebuild the screen.

  6. Inside setState(). You update the _joke variable with the value retrieved from the API. Flutter will use this value and render it onscreen shortly.

If you’re wondering why classes and variables are prefixed with _, it’s to do with the way Dart handles visibility. This short post helps explain how it works.

With the state update handled, the final thing to do is to tell Flutter where the joke should appear.

In the build() method in _MyHomePageState, update the Children objects to the following:

children: <Widget>[
            Text(
              '$_joke',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],

Here, you remove one of the Text objects and update the other to show the value of _joke. Text objects render TextFields in your app.

Update the floatingActionButton to call the _getJoke method when it is pressed.

floatingActionButton: FloatingActionButton(
        onPressed: _getJoke,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      )

Finally, to add abit of polish, scroll upto the MyApp class. Update the MaterialApp title and the MyHomePage title parameters to Jokes. This updates the title of your app screen.

Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Jokes',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.purple,
        // This makes the visual density adapt to the platform that you run
        // the app on. For desktop platforms, the controls will be smaller and
        // closer together (more dense) than on mobile platforms.
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Jokes'),
    );

With the Android emulator open from earlier, click the green Run button along the top of Android Studio. Whilst Flutter can hot reload the UI, we’ve added code that makes network requests. It’s safer to make sure the code is available by rebuilding the app.

Build the app from scratch

When the app appears in the emulator, press the button in the bottom right. A joke should be requested from the API and rendered on screen.

Joke rendered on screen

You’ve just took your first steps into Flutter using the Dart language!

Useful Resources

If you’re interested into diving more into Flutter. Here’s a few websites I recommend:

  • flutter.dev - The offical Flutter website has lots of information and tutorials to help learn what Flutter is capable of.

  • dart.dev - The Dart website is a great resource to expand your knowledge of Dart. The documentation is great and helped me to understand how Futures and aynchronous programming with Dart works.

  • raywenderlich.com The raywenderlich website has a up and coming collection of Flutter tutorials focused on developing real apps you’d see on a phone. (Full disclosure: I am a editor on the Android team at raywenderlich.com. I really believe the content is high quality though.)

  • It’s All Widgets This website is a collection of apps created using Flutter. It’s handy to get an idea of what Flutter is capable of. You can even add your apps.

That’s all for this series of posts. I hope you find this useful.

If you enjoyed these posts and like to hear more from me. Feel free to follow me on Twitter.