A full-fledged guide about GraphQL for Android

Vrajendra Bhavsar
Mindful Engineering
8 min readApr 20, 2022
MindInventory

GraphQL information

In the previous blog, we configured the project structure and added an empty schema.sdl file. In this part, we will see how to write Query and Mutation and the necessary steps to employ them.

Let’s get the schema

There are two ways, one is manually from the playground, and another is using the config file provided by JS graphQL plugin.

1. Manually from the playground

First, open GraphQL Playground here is the link:

https://www.graphqlbin.com/v2/new

Paste Rick and Morty API link in the GraphQL Playground:

https://rickandmortyapi.com/graphql

When the playground is open, you will see on the right side two tabs: DOCS and SCHEMA.

Click on SCHEMA, and copy-paste the code into schema.json

2. Using graphQL config file

In the folder where you have kept the schema file and Query files, add the config file as below with your URL and agent that you use.

It’s a part of the JS graphQL plugin, which enables you to make queries and mutation requests.

{
“name”: “Untitled GraphQL Schema”,
“schemaPath”: “schema.sdl”,
“extensions”: {
“endpoints”: {
“Default GraphQL Endpoint”: {
“url”: “https://rickandmortyapi.com/graphql",
“headers”: {
“user-agent”: “JS GraphQL”
},
“introspect”: false
}
}
}
}

Now to download schema from the back end, run the following command from the android terminal.

./gradlew downloadApolloSchema \
--endpoint=”https://rickandmortyapi.com/graphql" \
--schema=”app/src/main/graphql/com/example/schema.graphqls”

You can check Query in Playground (aka GraphiQl)

query CharactersData {
characters {
results {
id
name
episode{
name
episode
}
}
}
}

The query name is CharactersData for Apollo to generate a Kotlin file. We have to give the query a name.

The next lines are called fields which describe what we want to query.

Let’s Create a Query file

Create a new file in the same package like your schema.sdl

Create the query file, E.g. CharactersData.graphql

Copy the query that you tested in the left panel of the playground and paste it in your CharactersList.graphql file.

Now sit back and Rebuild the Project

Apollo client will create a Kotlin file of the CharactersData.graphql file. The client will automatically generate a model class based on your query file.

Search for CharactersDataQuery.Here .kt file will be auto-generated with Query postfix.

Open the file CharactersDataQuery.You can search it in Android Studio by using Ctrl + Shift + F.

There you will find a Result data class with fields we need for our list query.

data class Result(
val __typename: String = "Character",
val id: String?,
val name: String?,
val status: String?,
val species: String?,
val gender: String?,
val origin: Origin?
)

Building an Apollo client

Now we need an instance of ApolloClient. Before implementing the CharactersRepositoryImpl let us implement the class for the ApolloClient. Create a new package and name it a network. Create there a class CharApiService.

As you can see this class creates the ApolloClient and does the network call to the Rick and Morty API endpoint.

The builder offers a collection of ways to configure the client:

  • serverUrl(): This is used to define the URL of the API that is going to be communicated with
  • okHttpClient(): Provide an okHttp client reference to be used when making requests
  • logger(): Provide an instance of a com.apollo.graphql.logger to be used for logging
  • addApplicationInterceptor(): Add an ApolloInterceptor that can be used to observe the entire lifecycle of a request
  • defaultCacheHeaders(): Provide a key/value pair collection of cache headers in the form of an apollo CacheHeaders reference
  • defaultHttpCachePolicy(): Declare the cache policy to be used for GraphQl operations other than mutations
  • httpCache(): Provide configuration (in the form of an Apollo HttpCache reference) to be used for the request + response cache
  • dispatcher(): Provide an Executor reference to be used when dispatching requests
  • addCustomTypeAdapter(): Add an adapter used for serializing and deserializing custom GraphQl scalars

Executing an Operation

With our Apollo Client in place, we’re ready to execute our generated query CharactersDataQuery. For this we’re going to utilize the query function of the ApolloClient — this takes a reference to a generated Query class and returns us a reference to an ApolloQueryCall class.

Await is a suspending function that gives us a Result object that represents the response of our request. And the result will be returned as a suspending function.

With this in place, we have a starting point for executing query requests against our GraphQL schema!

Sample image that exemplifies how you can make use of query response.

Now let’s start with Mutation

So far we have covered graphQL and Query, we saw how to access or read data using queries, now let’s see how to change or “mutate” information using mutations!

What is Mutation

In GraphQL, there are only two types of operations you can perform: queries and mutations.
The mutation is a way to modify server-side data. If queries in the GraphQL are equivalent to GET calls in REST, then mutations represent the state-changing methods in REST (like DELETE, PUT, PATCH, etc)
In simple words, we use queries to fetch data, and mutations to modify server-side data.

Simple Mutation examples

Suppose we have a pet shop GraphQL API. Here, the query to fetch all the pets from the app might look like this:

query GetAllPets {
pets {
name
petType
}
}

Now suppose we want to add a new puppy or remove one from the Server. Mutation shines for such use cases :

mutation AddNewPet ($name: String!, $petType: PetType) {
addPet(name: $name, petType: $petType) {
id
name
petType
}
}

Here, the AddNewPet mutation expects values for the name and petType variables, these Input variable allows us to pass data that we want to be added to our table, inside the curly bracket we can define what response we want after adding a post.

The request data for this mutation holds the following shape:

{
“name”: “Rover”,
“petType”: “DOG”
}

In the mutation response, you could expect to see the following result.

{
“data”: {
“addPet”: {
“id”: 1
“name”: “Rover”,
“petType”: “DOG”
}
}
}

Structure of Mutation

The structure of Mutations looks very similar to queries. If you’ll recall, the general structure of a GraphQL operation looks like this.

One difference you will see is that the Operation type for the mutation will be mutation. We use the word “query” for queries and “mutation” for mutations.

Another important thing to note is that we signal the mutation we want to invoke by naming it exactly as it occurs within our server-side GraphQL API.

In the AddNewPet example, the name of the mutation is addPet, which should be the same as described in the schema.

Does your API support Mutation?

It’s crucial to understand the structure of schema before going further with mutation.

As we have discussed before, Schema describes the capabilities of your Server. First, check if your API supports Mutation. For that, go to your Schema.sdl file and search for Type mutation.

type Mutation {
bookTrips(launchIds: [ID]!): TripUpdateResponse!
cancelTrip(launchId: ID!): TripUpdateResponse!
login(email: String): String
uploadProfileImage(file: Upload!): User
}

If you find type mutation in your downloaded schema file, then you are good to follow the following steps where I will show you how to implement mutation.

Start by including essential parts to start with a mutation

Adding dependencies and schema files is the same as I have already discussed in the Query section. You can check API by yourself in graphiQL,

open GraphQL Playground here is the link:
https://www.graphqlbin.com/v2/new
Paste in the GraphQL Playground the Heroku API link: https://apollo-fullstack-tutorial.herokuapp.com/graphql

User authentication with Mutation

Firstly authentication is required, which will enable you to book and cancel trips in your app. Add Login mutation as below.

As we have discussed in the simple example section, the name of the mutation login should be the same as described in Schema.sdl .

type Mutation {
bookTrips(launchIds: [ID]!): TripUpdateResponse!
cancelTrip(launchId: ID!): TripUpdateResponse!
login(email: String): User
uploadProfileImage(file: Upload!): User
}

In the playground put the mutation, and add an email in the query section.

{ “email”: “me@example.com” }

Press the Play button, and see the response:

The response we are getting is a token that we will need while booking and canceling the trip.

Now go to Build -> Rebuild Project. Build your project to generate the UserLoginMutation class.

Let’s implement Apollo Client

Since Apollo Android is using OkHttp to handle HTTP requests, you will use OkHttp Interceptors to add headers to your GraphQL requests. Let’s create a Service and Interceptor class.

This interceptor appends an “Authorization: $token” HTTP header to every request.

Executing an Operation

With our Apollo Client in place, we’re ready to execute our generated mutation UserLogin. For this we’re going to utilize the mutate function of the ApolloClient — this takes a reference to a generated Mutation class.

Await is a suspending function that gives us a Result object that represents the response of our request as I have mentioned before in the Query section.

By creating an appropriate UI for taking user credentials you can make use of the Login Mutation for authentication. After successful authentication, you will receive a token in response which you will need for booking or canceling the trip. Check the implementation of Apollo client wherein the Interceptor we are passing this token as a Header.

Let’s book a flight 🚀 with Mutation

Now First, let’s check the booking and cancellation process in the Playground.

Booking process in the playground

see here how to pass the token to the header. In the query variable, you will have to pass id which you can see in the canceling process down below.

Canceling process in the playground

Let’s talk about the Trip, shall we?

Now that the user authentication part is completed, let’s book a flight. Add the BookTrip and CancelTrip mutations. In the same folder where you have kept Schema.sdl file, create files BookTrip.graphql and CancelTrip.graphql . Also, add Query to track the total number of booked Trips. dd TotalBookedTrips.graphql file.

Notice how the BookTrip the field takes a list as an argument but the mutation itself only takes a single variable. The CancelTrip mutation doesn’t use a list.

Here is a glimpse of how you can employ mutations to book or cancel the trip, and also with the query you can check the total booked trip.

This is a sample gif that exhibits how mutation would work for user authentication, booking, or canceling a trip and to substantiate the functionality of mutation using Query TotalBookedTripsQuery.

Okay, so that’s it for this part. If you have enjoyed this article give it a clap.

--

--