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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Flutter Networking Tutorial: Getting Started
30 mins
- Getting Started
- Exploring the Project
- Defining Important Terms
- Understanding Network Requests and Responses
- Understanding RESTful APIs
- Understanding Endpoints
- Understanding HTTP Methods
- Understanding HTTP Status Codes
- Understanding JSON
- Discovering Retrofit
- Understanding Asynchronous Programming
- Running the REST API Server
- Preparing for Development
- Adding Dependencies
- Generating Data Model Classes
- Implementing the REST Client Skeleton
- Performing GET Request
- Performing DELETE Request
- Performing POST and PUT Requests
- Where to Go From Here?
Performing DELETE Request
Next, you’ll implement the DELETE request method to delete a book from the list. To do so, open lib/ui/bookshelf_screen.dart and replace // TODO: implement DELETE network call
with the following snippet:
_dataSource
.deleteBook(books[index].id!) // 1
.then((_) =>
_bookStreamController.add(books..removeAt(index))) // 2
.catchError((_) {
ScaffoldMessenger.of(context).showSnackBar( // 3
const SnackBar(content: Text('Could not delete the book')));
});
In the code above:
- You made a DELETE request, passing the ID of the book to delete.
- If it succeeds, you remove the book from the local copy and refresh the stream controller.
- You show a snackbar in case of error.
Note that updating the book list in the stream controller causes the StreamBuilder
widget to rebuild. The framework calls its builder
method with a new snapshot value.
Notice also that the dismissed item disappears from the UI whether the request succeeds or not. But, the Dismissible
widget of the removed item may still be in the tree. This will cause a fatal error if you refresh the list by tapping the refresh icon button.
Next, similar to the GET request, open lib/network/rest_client.dart and add the following method:
@DELETE('/books/{id}')
Future<void> deleteBook(@Path('id') int id);
Unlike the GET request, the DELETE takes the book ID as a parameter. The name inside the curly braces — {id}
— in @DELETE
annotation has to match the one declared in @Path
. The name of the Dart method parameter is by convention the same.
Don’t forget to regenerate the code using build_runner
.
Finally, go to lib/network/data_source.dart. Find the // TODO: implement DELETE request
and replace the method with this code:
Future<void> deleteBook(int id) => _restClient.deleteBook(id);
Here, you just delegate the work to the REST client without any extra logic.
Now, reveal the terminal window where you’re running conduit. Then, launch the app and swipe some item to dismiss it. Here’s what you’ll see on the device:
And, this is what you’ll see in the terminal:
[INFO] conduit: GET /books 33ms 200
[INFO] conduit: DELETE /books/1 8ms 204
Note the HTTP status codes at the end of the lines.
Performing POST and PUT Requests
The POST and PUT requests share most of the code. The only difference is the subject of PUT has an ID, but the ID is null in case of POST. Tap the floating action button (+) to create a new book. This action will send the POST request. You can also edit a book by tapping it on the list. That’ll send the PUT request.
Open lib/ui/add_or_update_book_screen.dart and replace // TODO: implement network call
with the following fragment:
await widget.dataSource
.createOrUpdateBook(book) // 1
.then((_) => Navigator.pop(context, true)) // 2
.catchError((_) => ScaffoldMessenger.of(context).showSnackBar(// 3
const SnackBar(
content: Text('Could not create or update the book'))));
Breaking down the code above:
- Makes the POST or PUT request call.
- Navigating back to the previous screen in case of success.
- Displaying a snackbar in case of success.
The true
value of pop
call doesn’t have any meaning. You need anything other than null
.
Next, go to lib/network/rest_client.dart
and add the actual POST and PUT requests code:
@POST('/books')
Future<void> createBook(@Body() Book book);
@PUT('/books/{id}')
Future<void> updateBook(@Path('id') int id, @Body() Book book);
Notice the @Body
annotation on the book
parameters. It places the data inside the HTTP request body. There is an ID inside the book object, yet, the backend API takes an ID as a path element, analogous to the GET request.
As usual, regenerate the code:
dart run build_runner build --delete-conflicting-outputs
The distinction between PUT and POST happens in lib/network/data_source.dart. Locate // TODO: implement POST and PUT requests
there and replace it with:
if (book.id == null) {
await _restClient.createBook(book); // 1
} else {
await _restClient.updateBook(book.id!, book); // 2
}
In the code above, you have:
- The POST request call.
- The PUT request call.
Finally, launch the app and try to add a new book by tapping the floating action button with a + icon. You’ll see an effect like this:
Edit a book by tapping a book:
Congratualtions. You have successfully completed this article! You should now be able to make network requests using dio and retrofit.
Where to Go From Here?
Download the completed project files by clicking the Download Materials button at the top or bottom of the tutorial.
To learn more about Flutter networking using the http package and a different approach, take a look at the official documentation:
Or, explore more about the following topics:
- Conduit HTTP server.
- JSON and serialization.
- source_gen documentation.
- Our tutorial about parsing JSON in FLutter.
- The dio package.
We hope you enjoyed this tutorial. If you have any questions or comments, please join the forum discussion below!