While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or edited it to ensure you have an error-free learning experience. It's on our list, and we're working on it! You can help us out by using the "report an issue" button at the bottom of the tutorial.

It’s hard to do any sort of development without having to make some form of HTTP request, therefore, we’ll be looking at how to use the http plugin within Flutter.

Creating a New Flutter Project

In order to follow along with the setup we’ll be creating an example Flutter app. Assuming you already have the Flutter and Dart SDKs installed, run the following in your terminal:

# New Flutter application $ flutter create flutter_http # Open this up inside of VS Code $ cd flutter_http && code .

Adding the HTTP plugin

Head over to your pubspec.yaml and add the following plugin:

dependencies: flutter: sdk: flutter http: ^0.12.0+2

This is an official Flutter plugin published by dart.dev and it has 100 health score, therefore, we can trust the reliability of this plugin.

HTTP Requests

Our first task will be to create a class which we can use to interact with our API. We’ll create a new class named HttpService at lib/http_service.dart and add a getPosts function:

class HttpService { final String postsURL = "https://jsonplaceholder.typicode.com/posts"; Future<List<Post>> getPosts() async { Response res = await get(postsURL); if (res.statusCode == 200) { List<dynamic> body = jsonDecode(res.body); List<Post> posts = body .map( (dynamic item) => Post.fromJson(item), ) .toList(); return posts; } else { throw "Can't get posts."; } } }

As seen from the getPosts function, we’re firstly calling get from the http package on the postsURL .

Next, if that request was successful, we’re parsing the response and returning a List<Post> using Post.fromJson . Let’s go ahead and create the Post class at lib/posts_model.dart :

import 'package:flutter/foundation.dart'; class Post { final int userId; final int id; final String title; final String body; Post({ @required this.userId, @required this.id, @required this.title, @required this.body, }); factory Post.fromJson(Map<String, dynamic> json) { return Post( userId: json['userId'] as int, id: json['id'] as int, title: json['title'] as String, body: json['body'] as String, ); } }

In order to serialize the response, we’re returning a new Post with the fromJson method based on a JSON Map . In a production application, I’d recommend using something like json_serializable to handle the serialization automatically.

Displaying Posts

With this in mind, let’s create a new page named PostsPage at lib/posts.dart :

import 'package:flut_http/http_service.dart'; import 'package:flut_http/post_detail.dart'; import 'package:flut_http/post_model.dart'; import 'package:flutter/material.dart'; class PostsPage extends StatelessWidget { final HttpService httpService = HttpService(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Posts"), ), body: FutureBuilder( future: httpService.getPosts(), builder: (BuildContext context, AsyncSnapshot<List<Post>> snapshot) { if (snapshot.hasData) { List<Post> posts = snapshot.data; return ListView( children: posts .map( (Post post) => ListTile( title: Text(post.title), subtitle: Text("${post.userId}"), onTap: () => Navigator.of(context).push( MaterialPageRoute( builder: (context) => PostDetail( post: post, ), ), ), ), ) .toList(), ); } else { return Center(child: CircularProgressIndicator()); } }, ), ); } }

We’re using a FutureBuilder widget to interact with the getPosts() function. This allows us to determine when the List<Post> is ready and act accordingly.

If the snapshot.hasData is false, then we’re displaying the CircularProgressIndicator , otherwise we’re displaying the ListTile with various post information.

Let’s make sure we update main.dart with the home of PostsPage :

import 'package:flut_http/posts.dart'; import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'HTTP', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.deepPurple, ), home: PostsPage(), ); } }

Post Detail

If the user taps on the post, we’re looking to navigate the user away to a PostDetail page. Let’s build that:

import 'package:flut_http/post_model.dart'; import 'package:flutter/material.dart'; class PostDetail extends StatelessWidget { final Post post; PostDetail({@required this.post}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(post.title), ), body: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(12.0), child: Column( children: <Widget>[ Card( child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ ListTile( title: Text("Title"), subtitle: Text(post.title), ), ListTile( title: Text("ID"), subtitle: Text("${post.id}"), ), ListTile( title: Text("Body"), subtitle: Text(post.body), ), ListTile( title: Text("User ID"), subtitle: Text("${post.userId}"), ), ], ), ), ], ), ), )); } }

While this page doesn’t have any HTTP data, I’ve elected to add this to display the complete Post data.

DELETE

Another example of such HTTP request is the use of the delete method. For example, inside of our HttpService we can create a deletePost(int id) method:

Future<void> deletePost(int id) async { Response res = await delete("$postsURL/$id"); if (res.statusCode == 200) { print("DELETED"); } else { throw "Can't delete post."; } }

We can add an IconButton to the actions array within the AppBar so that whenever this is tapped a Post is deleted:

final HttpService httpService = HttpService(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(post.title), actions: <Widget>[ IconButton( icon: Icon(Icons.delete), onPressed: () async { await httpService.deletePost(post.id); Navigator.of(context).pop(); }, ) ], ), // ) }

Wrapping Up

In this article, we looked at how to interact with the Flutter http package. This allowed us to get a list of posts, as well as delete an individual post.