Read More »
I’ve got to ask you a few questions before starting:
- Do you have an app that consumes a REST endpoint?
- Do you still use plain HttpUrlConnection to connect to a server?
- Have you ever parsed a JSON string by hand?
Well, if you answered YES to one of these questions, This is the right talk for you!
Otherwise, it's still ok, and you’ll learn how to implement a good REST client in Android.
If you are wondering… what the hell is he saying… ok, thank you for staying!
Let’s take a look at THE MAIN INGREDIENTS OF A FAST WEB API
An Http 2 Endpoint (http is good, but this is new, and fast!)
Caching, don’t stress out your server
And a good rest client (not all are good)
Http2: it is the new revision of the popular Web Protocol HTTP.
It is based on SPDY (a google protocol) but now is maintained by the HTTP working group.
It is different from the 1.x version because of a few factors:
- It's binary, instead of textual
- It is fully multiplexed, instead of ordered and blocking
- It can therefore use one connection for parallelism
- It uses header compression to reduce overhead
- It allows servers to “push” responses proactively into client caches
It doesn’t require encryption, but it is strongly recommended , in fact it uses TLS.
But HTTP/2 Alone is not sufficient, we need help from the Caching system.
Mainly there are two types of caching systems. One is good for Dynamic apis and one is good to serve static APIs.
For dynamic apis you have to rely on a server side application such as APC, Varnish, Memcache.
For static APIs you can rely on the same system or there are a few HTTP headers you can use to specify caching rules for your resources.
Expires: Used in HTTP responses, the Expires header tells the client when the resource is going to expire.
Cache-Control: CC is a powerful header to manage your caching directives and strategies: it's a way of combining different directives about the response’s cache.
ETag: The etag is a unique identifier for your response: it is used on conditional requests, usually when a client gets a resource he also has in cache, sending to the origin server this identifier.
Last-Modified: If Date is the header which tells when the resource has been firstly generated, Last-Modified tells us when it has been… ..well, you guessed it.
And now let’s go directly to the point…
What is REST? Rest Stands for Representational State Transfer.
It's not a language but an architectural style.
It is platform and language independent and It consists in a coordinated set of architectural constraints applied to components, connectors and data elements.
In summary, the five key principles are:
- Give every “thing” an ID
- Link things together
- Use standard methods
- Allow Resources with multiple representations
- Communicate statelessly
It’s not the purpose of this talk to go in depth about rest, but how to implement a REST Client in Android.
There are some Android HTTP Clients out there
The plain DefaultHttpClient, Volley (from Google), Spring, Retrofit and many more…
Choosing a rest client for your app is like finding the right partner, each one has a particular style that makes you fall in love with her, but there is only one partner who completes you.
During my experience I’ve tried some of them, but in the end I chose Retrofit.
Retrofit is a Type-Safe Http client for Android. It is a simple HTTP client that uses annotations to:
describe HTTP requests, URL parameter replacement and query parameter support is integrated by default.
Additionally, it provides functionality for multipart request body and file uploads.
(for the file download I suggest you use the Download Manager)
Retrofit ships with support for OkHttp's RequestBody and ResponseBody types but the library is content-format agnostic.
These are the existing Retrofit converters and you can use them directly by integrating the respective gradle dependencies.
In the event that you need or want to create your own Retrofit response converter, it is possible, but it is an extensive process.
The most popular converter used is Gson, a JSON serialization and deserialization library that uses reflection to populate your Java model objects from JSON objects.
“If you have a small JSON, the GSON, gives the best result, but for large JSON, Jackson is better.”
Let’s now take a practical look at how retrofit could be implemented in our app.
It is pretty simple, you have to
- Create a POJO/JavaBean Model
- Create Retrofit Interface
- Create the Call object
- Execute the request
- Use the result
This is a simple POJO Java model.
(A JavaBean follows certain conventions. Getter/setter naming, having a public default constructor, being serializable etc. A POJO (plain-old-Java-object) isn't rigorously defined)
Retrofit turns your REST API into a Java interface! this is the interface.
You must declare the endpoints as annotations, and always as annotation you can define the headers.
After this, go to you Activity and Create the retrofit instance, create the Call object and use it through the two callbacks provided.
Just a note, keep in mind that in retrofit2 onResponse is still called even if there is a problem with the response. I mean, if the response is 404 Not Found, the OnResponse callback is called and you can retrieve the error body from the response object (response.errorBody().string()).
OnFailure is called only if the communication fails, but if the server responds, onResponse is called.
Retrofit permits you to make a synchronous or Asynchronous call, but remember that a network call must not be performed on the main thread.
If you find out that a call is not necessary, you can cancel it without problems. This thanks to the second release of Retrofit, the first version didn’t allow this.
Retrofit finally got the second major release in March of 2016.
Retrofit 2 comes with various fundamental changes and also includes breaking changes to the internal API.
They changed the package name in order to avoid conflicts, there is a simple way to declare a service with just a single pattern. A big improvement is the introduction of a way to cancel the ongoing transaction. Retrofit 2 comes with a new URL resolving concept, more similar to the html tag href, a good pattern is to make the base URL: always ends with / and the interface endpoints DO NOT start with /
In this new version Okhttp is now required and is automatically set as a dependency.
But what is OkHttp
OkHttp is a modern, fast and efficient Http client which supports HTTP/2 and SPDY and does a lot of stuff for you.
Reading how many things OkHttp does - is a good way to understand how hard networking is: Connection pooling, gziping, caching, recovers from network problems, sync and async calls, redirects, retries … and so on.
OkHttp is a very capable networking tool out of the box, without the need of any REST library and it probably is the library most developers would choose if they could only include one library in their projects.
OkHttp sits on top of Okio, a library that complements java.io and java.nio to make it much easier to access, store, and process your data. It provides fast I/O and resizable buffers.
OkHttp can be used in many libraries such as Volley and can be used as an http client for Picasso, glide, fresco…
Since the HTTP connection layer is in OkHttp you can use its interceptors.
Interceptors are a powerful mechanism that can monitor, rewrite, and retry calls.
Interceptors can be chained.
Suppose you have both a compressing interceptor and a checksumming interceptor: you'll need to decide whether data is compressed and then checksummed, or checksummed and then compressed.
OkHttp uses lists to track interceptors, and interceptors are called in order.
Here’s an example.
You have to use the retrofit builder and add your own OkHttpClient with its interceptors.
The most used interceptor is the Logging interceptor.
It is an OkHttp interceptor which logs HTTP request and response data.
The logs generated by this interceptor when using the HEADERS or BODY levels has the potential to leak sensitive informations, don't forget to disable them in production level environment.
In this talk, based on my experience, I will tell you about two levels of caching.
The first with OkHttp (a soft caching) and the second is a more persistent cache, with a database.
As we used OkHttp as a network layer, we use it as a caching bucket.
Response caching uses HTTP headers for all configurations.
You can add request headers like Cache-Control and OkHttp's cache will honor them.
As I mentioned before, there are cache headers to force a cached response, force a network response, or force the network response to be validated with a conditional GET.
To cache responses, you'll need a cache directory that you can read and write to, and a limit on the cache's size. The cache directory should be private, and untrusted applications should not be able to read its contents!
This is what I call soft caching. What I mean with persistent caching is related to storing data in a persistent storage.
There are many android storage options:
- Shared Preferences
- Internal/External Storage
- and Realm
You have to choose the right one in order to improve the performance on your app
In this case, Realm wins hands down.
Realm is the first database built from the ground up to run directly inside phones, tablets and wearables, it's not an ORM on top of SQLite. Instead it uses its own persistence engine.
Realm uses very little resources, is incredibly easy to use, and lets you interact with your data faster than any current alternative.
It is cross platform and it supports advanced features like Encryption, graph queries, and easy migrations.
Realm data uses very little disk space and requires no serialization & deserialization, and because it’s cross platform, you’ll get much better performance passing realm files around than shipping SQLite databases or chunks of JSON.
To Get Started check out the link on this slide.
Realm is very Fast, is still up to 100x faster than some SQLite ORMs and on average 10x faster than raw SQLite and common ORMs for typical operations.
A core feature I’d like to tell you about is the Realm Proxy classes. Realm generates a proxy class for each RealmObject at compile time. These objects themselves don’t contain any data, but instead access the data directly in the database.
This is useful when for instance we have a list and our content changes frequently.
How can we integrate it with Retrofit?
In order to use it in our environment, we have to look at the doc, which says: Retrofit does not automatically add objects to Realm, instead you must manually add them using the realm.copyToRealm() or realm.copyToRealmOrUpdate() methods.
Here you are! In the OnResponse callBack check if the response is successful and create the transaction.
I’ve made a short digression about how to create an HTTP/2 backend without knowing a lot of backend programming.
The purpose is to create a static endpoint that serves a static json. It’s not so common but sometimes it is enough.
In order to do this, AppEngine will come in handy. Go to console.developers.google.com and create a new project.
For simplicity's sake I’ve chosen Python with Flask. It is very easy, change the project-id in the sample app, edit a few Lines of code so the backend can read the data from the disk and serve it as an application/json response.
Go to the start page of AppEngine and download a sample app in the language you prefer.
AppEngine supports Python, Java, Php and Go.
To conclude my talk I’ve made a Demo…
We are hiring! duk.ma/jobpositions