Your Second Flutter App

Nov 30 2021 Dart 2.13, Flutter 2.2.3, Visual Studio Code

Part 1: Parse Network Data

5. Make a Network Call

Episode complete

Play next episode

Next
About this episode
See versions

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 4. Use a Model & Repository Next episode: 6. Parse the Network Response

Most mobile apps make network calls to the Internet to send and retrieve data to a backend server or API.

The sequence of events in a typical network call is as follows: your app sends a request to a remote server; the server processes the request and sends a response back to your app; your app processes the response and then takes an appropriate action. In some cases the action might be to show the response data to the user, or, the app may save the data to a database within your app.

A typical network call from a mobile app is what is known as a REST API, of which the raywenderlich API is an example. The request/response sequence just described follows the REST API pattern. REST API calls are made using a network protocol called HTTP, which stands for HyperText Transfer Protocol. To learn more about HTTP, you can watch this episode from our course “Server Side Swift with Vapor”.

The response is returned in JSON otherwise known as Javascript Object Notation. This is a machine independent format used to pass data around. A lot of REST service use JSON because it is easy to understand and parse. JSON is beyond the scope of this tutorial. If you are interested in learning more about JSON, check out a link in the author notes.

In this episode, you’ll learn how to make an http request in Flutter. In the next episode, you’ll see how to process the response that comes back from the server.

Open your project in progress or download the current starter project. We want to make an http request. There’s actually a flutter package that allows us to do this. There’s a number of ways to add a package to our project. I prefer to use the terminal which is integrated right into Visual Studio itself.

First, let’s check out the http package. Open up a browser and navigate to the following url:

https://pub.dev/packages/http

You’ll some documentation from the package. You’ll see a brief description followed by examples. Click on the Installing tab. You’ll see that it provides instructions for the terminal. Copy the With Flutter commands and return back to Visual Studio. Paste it in the terminal. Congrats! You installed a dependency.

Open up course_repository.dart in the repository folder. We need to import the dependency. Switch back to your browser and select the ReadMe tab. Look under using. You’ll see an example import statement. Copy it. Return back Visual Studio Code and paste it.

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

Now in getCourses, add the following after the if statement.

final uri = Uri.parse(url);
final response = await http.get(uri);

First we convert the URL to a URI, and make the actual request. Now we need to convert the response to JSON. You’ll learn more about JSON conversion in the next episode. For now, we’ll do a conversion.

final apiResponse = json.decode(response.body) as Map<String, dynamic>;
print(apiResponse);

We’re getting an error because we need to import the convert library. Select the json and press command-. on mac or control-. on windows. Select import library dart:convert.

At this point, we made a request to the network and printed out the response. Now we want to see that response. Remember, a network request can take a long period of time so we need to wrap it in a future. To do this, we’ll create a controller. The controller will make the network request in a future.

Create a new file in the ui / courses folder. Call it, courses_controller.dart. Then create a simple class.

class CoursesController {
}

Next import the repository, course repository, and course.

import '../../repository/repository.dart';
import '../../repository/course_repository.dart';
import '../../model/course.dart';

Then add a repository property.

final Repository _repository = CourseRepository();

Now add a fetchCourses method. This will return a future. This future will return a list of courses.

  Future<List<Course>> fetchCourses(int domainFilter) {
    return _repository.getCourses(domainFilter);
  }

So now we have our controller. Now we need a page to display the results. Granted, our network call is only printing to the console at the moment, but in an upcoming episode, you’ll have it print results to the screen instead. Let’s use our courses page. Open it up.

Import our courses controller and add a property to it in the _CoursesPageState.

final _controller = CoursesController();

Okay, now to to make the network request. We will do this in our build method. This poses a problem. The build method will be called right away yet we don’t know when our network request will take. Thankfully Flutter has provided a FutureBuilder. This informs the framework when the future is complete. Add the following:

    return FutureBuilder<List<Course>>(
        future: _controller.fetchCourses(Constants.allFilter),
);

The FutureBuilder comes with a builder property. This passes in a context and the snapshot. The snapshot will contain various states of the Future as it comes back. Use the data property of the snapshot to hold the list of courses.

builder: (context, snapshot) {
  final courses = snapshot.data;
  if (courses == null) {
    return const Center(child: CircularProgressIndicator());
  }
  return const Text('RWCourses');
}

If there are no courses return, the ui will display a circular progress indicator, letting the user know that something is occurring in the background. Otherwise, we’ll use a simple text to print a message on the screen.

That said, once the Text is printed, our api response will also be printed in the console. We’re getting one more error. Make sure to import course.dart.

import '../../model/course.dart';

Now to call it. Open rwcourses_app.dart. First, import the courses page.

import 'ui/courses/courses_page.dart';

After the appBar property, add a body property, passing in the courses page.

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(Strings.appTitle),
    ),
    body: const CoursesPage(),
  );
}

And that’s it. Build and run or hot reload. Now look at the console. We’ll see the api response printed to the console all ready to be used.