Flutter HTTP Tutorial and Examples
How to perform various HTTP Requests in Flutter, and Classes involved in this package.
Let's start by discussing the Requests
class.
Requests:
In Flutter, a HTTP request where the entire request body is known in advance is represented by the Request
class.
This class does derive from the BaseRequest
which directly derives from the Object
class.
Here's it's inheritance hierarchy:
Object -> BaseRequest -> Request
Here's it's constructor:
Request(String method, Uri url)
That will create us a new HTTP Request.
You use the Request
class if you want more fine grained control over your HTTP Requests. Otherwise there are more generic methods we can use depending on the request type.
1. HTTP GET Request
In Flutter, we can make a HTTP GET Request using the get()
function.
Here's it's definition:
Future<Response> get (dynamic url, {Map<String, String> headers});
The request is sent with the given headers to the given URL. As a URL you allowed to pass either a Uri
or a String
.
Then the get()
function will automatically initialize a new Client
when it's we make our HTTP GET request. On the hand as when our request is finished then it will close it as well. It's recommended that if you're planning on making multiple requests to the same server, then you use a single Client for all of those requests.
Implementation:
Future<Response> get(url, {Map<String, String> headers}) =>
_withClient((client) => client.get(url, headers: headers));
Here's a real world implementation of the get()
function to make a GET request to a server:
final JsonDecoder _decoder = new JsonDecoder();
Future<dynamic> get(String url) {
return http.get(url).then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 400 || json == null) {
throw new Exception("Error while fetching data");
}
return _decoder.convert(res);
});
}
2. HTTP POST request
HTTP POST requests, generally mean you sending some data to the server. This is a common scenario and you do make this request probably on a daily basis, whether logging in to your account or filing your tax returns.
So Flutter and Dart provide us with an easy to mae them using the post()
function/method.
The post()
method is defined as follows:
Future<Response> post (dynamic url, {Map<String, String> headers,dynamic body,Encoding encoding})
This method will make a HTTP POST request with the given headers and body to the given URL. Again, that given URL can be a Uri
or a String
.
The body
we are passing there is the request body. This can be:
- String.
- List.
- Map<String,String>
(a). String
If it's a String, then it will be encoded using encoding and used as the body of the request. The content-type of the request will default to "text/plain"
.
(b) List
If the body
is a List
, then it's used as a list of bytes for the body of the request.
(c). Map<String,String>
If body is a Map
, it's encoded as form fields using encoding. The content-type of the request will be set to "application/x-www-form-urlencoded";
. This cannot be overridden.
Here's an example implementation:
Future<Response> post(url, {Map<String, String> headers, body,
Encoding encoding}) =>
_withClient((client) => client.post(url,
headers: headers, body: body, encoding: encoding));
Here's an implementation in real world usage:
final JsonDecoder _decoder = new JsonDecoder();
Future<dynamic> post(String url, {Map headers, body, encoding}) {
return http
.post(url, body: body, headers: headers, encoding: encoding)
.then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 400 || json == null) {
throw new Exception("Error while fetching data");
}
return _decoder.convert(res);
});
}
Full Example
Let's say you want to fetch data from MongoDB Server and populate a ListView in our flutter application. We'll be making a HTTP GET Request.
(a) pubspec.yaml
dependencies:
mongo_dart: ^0.3.1
shelf_rest: any
http: any
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
(b) main.dart
import 'package:flutter/material.dart';
//import 'package:mongo_dart/mongo_dart.dart' as mongo;
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
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 press Run > Flutter Hot Reload in IntelliJ). Notice that the
// counter didn't reset back to zero; the application is not restarted.
primarySwatch: Colors.blue,
),
home: new Names(
pageName: "Facebook Code Test",
),
);
}
}
class Names extends StatefulWidget {
final String pageName;
const Names({Key key, this.pageName}) : super(key: key);
@override
_NamesState createState() => _NamesState();
}
class _NamesState extends State<Names> {
List<Name> _names = new List();
List<Widget> _namesTiles = new List();
String uriString =
"mongodb://DATABASESERVER:27017/rpc1";
String collectionName = "names";
@override
void initState() {
super.initState();
_getNames();
}
_getNames() async {
http.Response response = await http.get("http://SERVICEIP:8000/list");
String body = response.body;
List data = jsonDecode(body);
for (Map raw in data) {
Name name = new Name()
..firstName = raw['firstName']
..lastName = raw['lastName'];
// print("Received $name");
_names.add(name);
}
// print("received $_names");
setState(() {
for (Name found in _names) {
Text text = new Text("$found");
_namesTiles.add(text);
}
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
appBar: AppBar(
title: Text(widget.pageName),
),
body: ListView.builder(
itemBuilder: (context, index) => _namesTiles[index],
itemCount: _namesTiles.length,
),
);
}
}
class Name {
String firstName;
String lastName;
@override
String toString() {
// TODO: implement toString
return "$firstName $lastName";
}
}
Download Full source code here.