How to add HTTP Package (Flutter)

To make GET requests we need to use the http package. You can find the http package on Dart Pub.

Let’s start by creating a new Flutter app project using:

$ flutter create xkcd_app

and installing the HTTP package by adding the following to pubspec.yaml:

networking/xkcd_app/pubspec.yaml

dependencies:
http: ​"​​^0.12.0+1"

Run flutter packages get to download and install the package if you aren’t using the IDE plugins (which will do it automatically for you after you make changes to pubspec.yaml).

USING THE HTTP PACKAGE

The HTTP package can be used to make HTTP requests of all kinds.

All of them are asynchronous, which means that, by default, they are ran in a separate thread without affecting the rest of the app’s execution. You can choose to make them behave exactly like synchronous functions if their return value is vital to the prosecution of the app’s execution.

Asynchronous Code in Dart

There are many ways to run asynchronous code in Dart, but the basic concept has already been explained in the previous chapter: calls to functions that return a Future (or Stream, which we won’t be using in this chapter) and run in a separate thread are called asynchronous.

We can get the data returned by an asynchronous function by using an await expression:

var returnedData = await asyncFunction();

This can only be done in async functions and async functions have to return Futures, so asynchrony tends to propagate to all of the calling methods.

Making GET Requests

An HTTP request is made using http.get, which is an async method that returns a Response inside a Future.

We can unwrap the inner Response using await:

var​ latestComicResponse = await http.get(​"https://xkcd.com/info.0.json"​);

and we can get the body of the response as a String by querying its body attribute, like we will need to do when we build our XKCD app:

​var​ latestComicString = latestComicResponse.body;

We could also do everything in one line, enclosing the await expression in parentheses:

​var​ latestComicString = (await http.get(​"https://xkcd.com/info.0.json"​)).body;

HTTP headers can be set by setting the headers named arguments to a Map<String, String>, like in the following example:

http.get(
"http://example.com/exampleGet?testAttr=​​$val1​​&testAttr2=​​$val2​​"​,
headers: {
"Accept"​: ​"application/json"​,
"Accept-Charset"​: ​"utf-8"​
}
)

Wikipedia has a comprehensive list of standard HTTP headers.

The http package also provides http.read() and http.readBytes(), which are, respectively, just like http.get()’s body and bodyBytes attributes.

For example, you could go from calling:

String​ res = (await http.get(​"http://example.com"​)).body;

to just:

String​ res = await http.read(​"http://example.com"​);

or go from:

String​ res = (await http.get(​"http://example.com"​)).bodyBytes;

to just:

String​ res = await http.readBytes(​"http://example.com"​);

Be careful, though, as you lose other attributes of the Response object (the type of data http.get returns), such as:

  • headers, which is needed when you need to read the response’s headers;
  • contentLength, which is the size (in bytes) of the response.

Making Other Requests

Other kinds of HTTP requests are also supported, and all of them support setting headers in the way we’ve just seen and all of them return Future<Response> objects:

  • A POST request is made using http.post, the request URL is provided as a positional argument and you can set the request body by setting the body named argument to whatever you want.
  • A PUT request is made using http.put, the request URL is provided as a positional argument and you can set the request body by setting the body named argument to whatever you want.
  • A DELETE request is made using http.delete, the request URL is provided as a positional argument.
  • A PATCH request is made using http.patch, the request URL is provided as a positional argument and you can set the request body by setting the body named argument to whatever you want.
  • A HEAD request is made using http.head, the request URL is provided as a positional argument.

Whenever it’s possible to add a body attribute it’s also possible to add an encoding attribute, which is of type Econding and is used to define the body’s encoding. Some Encoding subclasses are AsciiCodec and Utf8Codec.

PARSING THE JSON RESPONSE BODY

The HTTP response body is just a string, so it is not useful unless it is parsed.

Manually parsing it would be incredibly time-consuming and pointless, since the dart:convert built-in library already provides a constant called JSON, which is of type JsonCodec, meaning it exposes two methods:

  • json.encode(obj), which converts the obj object to a JSON string.
  • json.decode(str), which converts the str JSON string to a Dart object.

In our specific case, we want to convert a JSON string to a Map<String, dynamic>, which allows us to access each of the comic’s attributes by name as we’ll see in the next section.

Using dart:convert, if we had previously stored the response body of a call to XKCD’s API to a variable called latestComicString, we would be able to convert it to a Map by using:

​ Map<​String​, ​dynamic​> latestComic = json.decode(latestComicString);

So the code we would add to our app if we needed to store the latest comic in a Map variable is:

Map<​String​, ​dynamic​> latestComic = json.decode(​   
await http.read(​"https://xkcd.com/info.0.json"​)​ 
);

Learn more about Flutter

Written by

XR Developer responsible for end-to-end development of XR solutions spanning multiple domains, by using various XR and WebXR libraries.

Leave a Reply