Make no mistake, the majority of android apps need some pieces of networking, it’s hard to think of any real, problem-solving app that completely dispense with the Internet. And when it comes to networking, most android developers will be familiar with REST.
It has been the industry standard for designing web APIs. It offers some great ideas, with a pretty straightforward way to communicate with it using one of the many clients out there, with Retrofit being the most favourable one for android.
However, REST APIs have shown to be too inflexible to keep up with the rapidly changing requirements of the clients accessing them, that’s why GraphQl was born. GraphQL is a query language for the APIs for getting your data. It was created by Facebook back in 2012 to power their mobile applications and then open sourced in 2015
GraphQl has many advantages over REST, these advantages are of great importance when dealing with massive data accessed via different clients, among these advantages are the following:
With GraphQl, clients possess power over the server, different clients can get completely different data, I.e. each client can define what they would like the responses to include. That totally differs from REST where clients don’t have that luxury, they all will get the same response and have to handle it to get what they’re interested in.
Using REST, we used to make a number of requests to fetch the data we need right? Well, these days are gone. With GraphQl, one request could be more than enough for what you need. Let's clarify by an example. Let's say our blogging application needs to display the titles of the posts of a specific user. The same screen also displays the names of the last 3 followers of that user.
In the example, these could be:
Endpoint to fetch the initial user data. Secondly, there’s likely to be:
Posts endpoint that returns all the posts for a user. The third endpoint will then be:
The followers that returns a list of followers per post. That means you have to handle three different requests to three different end point to fetch the exactly-required data, quite a headache.
With GraphQl on the other hand, you can fetch the same data with only one request. You just wrap the data you want to get in a single query, send that query to the GraphQL server. The server then responds with a JSON object where these requirements are fulfilled. In other words, you get exactly the same data you need:
Another major advantage is that you don’t create the model classes yourself like you used to do in REST, you get it created with just minimum effort.
Simply Put, overfetching is getting way more data than you need, using rest in our example, you would probably get other data you don’t care about now, like for example the comments for each post along with the time they were created at. It’s very difficult to design the API in a way that it’s able to provide clients with their exact data needs. One the other hand, underfetching means that a specific endpoint doesn’t provide enough of the required information, so you have to send many requests.That being said, we highly encourage you to adapt GraphQl in your next project.
So now your team is convinced that GraphQl is REST 2.0 and it’s high time you all migrated into it. The backend people have already prepared the server. The question now is, how to get your android project GraphQl-compatible.
To start using graph in android, the first thing you need is a client to communicate with the server some sort of Retrofit counterpart. The client available for android apps is Apollo-Android. A client designed primarily with Android in mind and can easily be used with both java and kotlin.
In your project's build.gradle - Top-level build file - file add this plugin:
In your app’s build.gradle apply the plugin:
apply plugin: 'com.apollographql.android'
And add this dependency:
implementation 'com.apollographql.apollo:apollo-runtime:x.y.z' implementation 'com.apollographql.apollo:apollo-android-support:x.y.z' implementation 'com.squareup.okhttp3:logging-interceptor:latestVersion'
Refer to Apollo-android repo on the github here replace “x.y.z” with the latest available version.
Apollo uses OkHttp behind the scene, so don’t forget to add its dependency as well.
ApolloClient uses OkHttp under the hood for handling network requests. So you will need to create an instance of the OkHttpClient and pass it to the ApolloClient builder.
The simplest apollo client can thus be built as follow:
Val apolloClient = ApolloClient.builder().serverUrl(BASE_URL) .okHttpClient(OkHttpClient()).build()
If you need to send header values with your GraphQL requests, such as in case of authorization, you can add those to your OkHttpClient instance by means of an Interceptor. Setting connection timeout and readtimeout will also be configured in the OkHttp client.
Now you’ve added the dependency and built the client, your project is almost ready to communicate with the server. You just have to tell the server what data you need, and how the data fetched from the server should be structured, this is can be done with minimum effort thanks to the great Apollo. We'll come back to it later but let’s concentrate on the concepts for now.
You can communicate with the server in three different ways, more technically speaking GraphQl support three operations namely “query”, “mutation” and “subscription”.
Query is GET counterpart in graph where you ask the server for some data named “fields”, and as you might have guessed it, mutation is POST counterpart where you make some changes to the server, so what about subscription? Subscriptions are similar to queries in that they specify a set of fields to be delivered to the client, but instead of immediately returning a single answer, a result is sent every time a particular event happens on the server. Think of it as Socket.io alternative.
Comprehensive details on theses operation are well documented in Graphql website, it’s highly recommended to visit the website at:Graphql
The bottom line is that you must specify the operations you’re interested in .graphql files. These files must be located in a particular directory. That directory should be a folder under src/main on the same level as your java/res folder, and it should be named “graphql”. (image). That folder should contain all your .graphql files as well as the schema.
Yes, In every project where you use GraphQl you must include the schema in the same directory as the operations files, the schema is a .json file describing the structure of the database, it’s of great importance for Apollo to know what model classes it should create for you.
Based on your downloaded:
File and the contents of your:
Files you will have generated Java classes in the following directory:
There will be one Java class for each of your queries with nested classes for reading the network response:
How will you get this schema thing? You need to have Apollo-CLI installed and specify the URL from which the schema should be downloaded, got confused let’s wrap things up.
To download the schema, you can use Apollo CLI and just specify the base url and you’ll get it downloaded in json format.
Apollo-CLI is some sort of tool that downloads the schema for you from a specific url, and also generates the necessary model classes you’ll need based on your schema and the content of your .graphql files.
To install Apollo CLI, run that command in the terminal:
$ npm install -g apollo
Note: you need to have Node.js installed.
Then download the schema by running that command:
apollo schema:download --endpoint="your base url” schema.json
So now just rebuild your project and you’ll get a class generated for each operation, You can use the generated classes to make requests to your GraphQL API.
After rebuilding the project you’ll get generated class corresponding to the content of your .grahpql files, can use with the apollo client you built earlier to send the request and handle the response in the way you like.
One thing you should notice is to remember that appollo handle the response on the background thread, so to update your views you need to post back to the main thread or alternatively use can RXJAVA, a topic we may discuss later.