Photo by Soroush Karimi on Unsplash

GraphQL is a query language for your API. This allows developers to interact with existing web services and databases in a new way. Instead of relying on a predetermined output structure from the API, we can “query” it instead and choose the fields we’re interested in. GraphQL also supports updating objects in your data source via what it calls “mutations”. We’ve began transitioning our Android application to take advantage of our API’s GraphQL endpoint.

Here’s what’s been involved in the changeover…

Learn

First we had to start learning about GraphQL. It was new to us and we needed to get up-to-speed with the basics. Here’s a fun video that does a good job of covering them:

A few key GraphQL terms to really understand are:

Fields/Types

Variables

Fragments

Queries/Mutations

Further, I attended the GraphQL on Android talk at Droidcon NYC 2017. This helped me wrap my head around the benefits of switching. I also had the opportunity to pepper the speakers with additional questions later on. This convinced me that it would be a good addition to our Android codebase.

After that, I spent some time executing queries and mutations against our staging environment. Our development team set up GraphiQL against the API. It’s an in-browser GraphQL IDE. This allowed me to see GraphQL in action, and helped to ensure that the queries I created worked as intended.

Screenshot of GraphiQL

Setup

The best way we’ve found to work with GraphQL on Android is to use the Apollo Gradle Plugin. Apollo-Android is a GraphQL client that generates Java models from your GraphQL queries and mutations. It also works seamlessly with OkHttp as the networking layer. This comes in handy if you’re using something like Retrofit already for your API calls.

We’re using Dagger to handle dependency injection in our application. To support the Apollo Client we created one new dependency in our ApiModule . This allowed us to reuse our existing OkHttpClient dependency.

@Provides

@Reusable

open fun provideApolloClient(okHttpClient: OkHttpClient): ApolloClient {

return ApolloClient.builder()

.serverUrl(this.baseUrl+APOLLO_ENDPOINT)

.okHttpClient(okHttpClient)

.build()

}

You will also need to download the schema.json file from your GraphQL server. This is how the plugin knows how to generate your classes with the appropriate field types. Since we use header based authorization, I used the following command to get access to our schema file:

apollo-codegen download-schema <your_URL> — output schema.json — header “Cookie: Cookie_Name=Value”

Then just make sure you follow along with the steps outlined in the apollo-android repository to place all of your files in the correct locations.

Implement

Now for the fun part, the implementation. When we first started porting over some of our previous REST calls to GraphQL, I found lots of examples of making queries, but very few on handling mutations. So let me cover that here.

Let’s say you want to update an existing Customer in your system. With REST, that would be a PATCH request to let’s say your /customers/{id} endpoint. This is how to approach it with Apollo-Android.

You should create a .graphql file that will contain your mutation code. Here’s an example file that receives the id of the customer and the customer object as input to the mutation:

// CustomersMutation.graphql mutation updateCustomerInfo($id: Int!, $customer: CustomerInputObjectType!) {

customerUpdate(id: $id, customer: $customer) {

id

}

}

2. You should rebuild your project so that the plugin can generate your mutation classes for you.

3. Now wherever you would like to execute your request, you can access your generated mutation class and its associated builder. The builder will provide methods that map to the names of the variables you defined in your mutation.

// UpdateCustomerRequestJob.kt val mutation = UpdateCustomerInfoMutation.builder()

.id(customer.remoteId)

.customer(getCustomerInputObject())

.build()

Notice that for the customer variable, it was defined as a CustomerInputObjectType . This came from our schema’s definition. Since it’s used to pass our Customer data to the API, I add an Extension function to our class to map the data.

private fun Customer.getCustomerInputObject(): CustomerInputObjectType {

return CustomerInputObjectType.builder()

.village(village)

.first_name(firstName)

.last_name(lastName)

.build()

}

4. Finally, with our mutation in place, we can use the RxJava integration to perform the mutation and then handle the results.

// UpdateCustomerRequestJob.kt Rx2Apollo.from(apolloClient.mutate(mutation))

.subscribeOn(Schedulers.io())

.observeOn(AndroidSchedulers.mainThread())

.subscribe({ handleSuccess() },

{ handleFailure() })

}

Reflect

There was some initial apprehension about moving to GraphQL. After all, we’re engineers, it’s in our nature to be skeptical. However, the transition has gone smoothly and we’re happy with the change. One thing we haven’t quite figured out yet, is how to support dynamically updating a header per request. We had this functionality with Retrofit and would love to be able to do the same with Apollo-Android.

References: