Flutter Networking Tutorial: Getting Started

In this tutorial, you’ll learn how to make asynchronous network requests and handle the responses in a Flutter app connected to a REST API. By Karol Wrótniak.

Leave a rating/review
Download materials
Save for later
Update note: Karol Wrótniak updated this tutorial for Flutter 3.10.0. The original version was written by Sagar Suri.

In today’s world, smartphones are the primary hub for many activities: entertainment, banking, photography and videography and shopping, among others. To do many of the things their users request, the apps on your smartphone need internet access.

If you plan to develop apps that fetch data from the internet, you’ll need to know about networking: how to make network requests, handle the responses and the errors. Throughout this tutorial, you’ll learn how to do that by building a Flutter app named Bookshelf, which displays a list of popular books. You’ll be able to change, add and delete a book from the list.

Here’s what you’ll do:

  • Learn how to run a RESTful API server using the conduit framework on your computer.
  • Familiarize yourself with GET, PUT, POST and DELETE requests.
  • Learn how to use the dio HTTP client to make network requests.
  • Learn how to use the json_serializable package to create and parse JSON.
  • Explore retrofit by connecting dio with json_serializable.
  • Understand Future, async and await.
Note: This tutorial assumes you have prior knowledge of Dart and the Flutter framework. If you’re unfamiliar with Flutter, please see Getting Started with Flutter.

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.

This article uses Android Studio. But you can also use VS Code or your favorite IDE with Flutter at the command line.

Run the starter app by pressing Play in Android Studio or using the keyboard shortcut Control-R on macOS or Shift-F10 on Windows or Linux. You’ll see this screen:
Bookshelf starter app main screen

Notice that nothing shows apart from a lorem ipsum placeholder. It’ll show a list of your favorite books after you complete the project.

Exploring the Project

Once you’ve run the starter project, it’s time to take a look at the project structure:

├── api
│   ├── bin
│   │   └── main.dart
│   └── lib
│       ├── api.dart
│       ├── books_controller.dart
│       ├── bookstore.dart
│       └── channel.dart
└── lib
    ├── main.dart
    ├── model
    │   └── book.dart
    ├── network
    │   └── data_source.dart
    └── ui
        ├── add_or_update_book_screen.dart
        └── bookshelf_screen.dart

Here’s the purpose of each directory:

  • api: Holds the server logic, you won’t work with files in this folder.
  • model: Contains the book data model class.
  • network: Holds the networking logic of the app.
  • ui: Contains UI screens for the app.

Defining Important Terms

Take a moment to be sure you understand the terminology used in this tutorial.

Understanding Network Requests and Responses

In simple terms, when you use apps like WhatsApp or Twitter, they try to transfer some data from or to a server. The diagram below is a simple illustration of that flow:

Network request and response

The app you’re using is the client. So, a client makes a network request to a server, and it answers with a response. There are different ways to transfer data this way. One of the most popular ones is through a RESTful API.

Understanding RESTful APIs

REST stands for REpresentational State Transfer. It’s an application program interface — API. It uses HTTP requests to get or send data between computers.

Communication between a client and a server mostly happens through RESTful APIs, and that’s what you’ll use in this tutorial.

Understanding Endpoints

An endpoint is an end-of-communication channel between the server and your app. Servers provide access to REST API endpoints through URLs. For example, if you have the URLs https://api.example.com/v1/users and https://api.example.com/v1/products the common prefix: https://api.example.com/v1 is a base URL. The variable suffixes /users and /products are the endpoints.

Note:, there has to be a slash separating a base URL and the endpoint. By convention, in Flutter, often there is no trailing slash in the base URL. But, the endpoints have leading slashes. The generated code under the hood concatenates a base URL with a path to make the full URL and then normalizes the result.
So the other way around (trailing slash in a base URL) or slashes at both positions will also work.

Understanding HTTP Methods

An HTTP method is an action you want to perform. There are several HTTP methods you can use in REST APIs. Here’s what they do:

  • GET: Downloads the specified resource. Requests using GET only retrieve data; they shouldn’t alter it.
  • DELETE: Deletes the specified resource.
  • POST: Submits data to the specified resource. Usually creates the new objects on the server.
  • PUT: Replaces the entire target resource with the uploaded one. It may create a new object if target does not exist.
  • PATCH: Applies partial updates to the target resource.
  • HEAD: Behaves like GET but returns no body. Useful for quick checks to see if something exists on the server or how big it is.

There are more HTTP methods, but the other ones are rarely used in app development. See the complete list on the MDN web docs. Note that the server doesn’t need to implement all the methods for all the endpoints.

Note the differences between PUT and POST. The PUT requests should be idempotent: No matter how many times you repeat it, the state on the backend should be the same. But, in case of POST, if you send the same request many times, you may multiply the results. For instance, create multiple objects on the server.
Usually, a PUT takes some unique identifier as a parameter so the logic on the backend can select the subject to change.

Understanding HTTP Status Codes

Each HTTP response contains a metadata. The most important part of it is the status code — a three-digit decimal number:

HTTP status codes

It tells client whether the request succeeded or not. You probably recall 404 – Not found errors, where 404 is the status code. In general, status codes range from 100-599:

  • 2xx — from 200 to 299 — means success.
  • 4xx and 5xx mean failure.
  • 1xx and 3xx exist only on low abstraction layers like HTTP client internals. They aren’t used in front-end development.
Note: The HTTP request can fail due to network issues like a defunct internet connection. In such cases, there’s no HTTP status because there’s no readable response. In this tutorial, you won’t be dealing with the HTTP status codes directly. The libraries you’ll use do it for you. They throw Dart exceptions in case of unsuccessful status codes.