Exploring Apollo GraphQL for Android

Exploring Apollo GraphQL for Android

From what looks like such a great client, it definitely lacks the documentation and community support that it deserves. In this blogging series, I’ll try to bridge the gap between what is documented and what you can achieve with Apollo’s GraphQL client for Android. Now let’s get the basics out of the way,

What is GraphQL?

"GraphQL decouples apps from services by introducing a flexible query language. Instead of a custom API for each screen, app developers describe the data they need, service developers describe what they can supply, and GraphQL automatically matches the two together. Teams ship faster across more platforms, with new levels of visibility and control over how their data is used." - apollographql.com

In simple words, GraphQL lets the client decide which data they want, rather than having the server send a fixed set of data. GraphQL is an alternative approach to building an API over REST.

Adding GraphQL to your Android project:

First of all you will need to add repository and dependency on Project level build.gradle file:

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.apollographql.apollo:apollo-gradle-plugin:x.y.z'
  }
}

x.y.z represents the version number you want to add. You can find the latest version number over at Apollo-Android GitHub repo.

Now apply the plugin on App level build.gradle file:

apply plugin: 'com.apollographql.android'

This should give you the core Apollo GraphQL client. To support Apollo GraphQL on Android we need to build apollo-runtime and android-support dependencies.

implementation 'com.apollographql.apollo:apollo-runtime:1.0.0'
implementation 'com.apollographql.apollo:apollo-android-support:1.0.0'
implementation 'com.squareup.okhttp3:okhttp:3.14.2'

This provides us with support for working with Android’s UI thread and Worker threads. We are building OkHttp, because Apollo GraphQL uses OkHttp as the underlying network driver.

Additionally, if you want Rx2 or Coroutines support then Apollo has you covered as well.

implementation 'com.apollographql.apollo:apollo-rx2-support:1.0.0'
implementation 'com.apollographql.apollo:apollo-coroutines-support:1.0.0'
  • Replace 1.0.0 with the latest version of the libraries

There’s one more step left before we get started. As Apollo handles the Database Schema on backend, we need to add schema.json in our Android project.

apollo schema:download --endpoint=http://localhost:8080/graphql schema.json

This will require you to install Apollo-CLI.

At the level of /main folder (inside your project) you need to create the following directory structure and paste the schema.json

Android-GraphQL-FileStructure.png

And that’s about it. We are ready to rock the GraphQL client.

Let’s write our first basic query

Create the file GetUser.graphql with the following text in the same location as schema.json:

query GetUser( $userId: String!, $phone: String ) {
  getUserDetails( userId: $userId, phone: $phone ) {
    name
    email
    age
  }
}
  • GetUser is the client side name for the query and getUserDetails is what the server expects as a query.
  • $userId, $phone are the variables that we declare to pass down query parameters.
  • 'name', 'email', 'age' are the variables that we want the query to return.

Now the actual execution of the query:

Following function builds and returns the Apollo client.

fun provideApolloClient( ): ApolloClient {
        return ApolloClient.builder()
            .serverUrl("http://localhost:8080/graphql")
            .okHttpClient(OkHttpClient().newBuilder().build())
            .build()
}

Now build your Android project which will trigger Apollo to generate all the needed classes.

Remember, Apollo also parse the response and generate classes for you. So there’s no need to build your own data class and then parse response with any JSON parsing libraries.

val apolloClient = provideApolloClient( )

apolloClient.query(
            GetUserQuery.builder()
                .userId(“provide-user-id”)
                .phone(“provide-phone”)
                .build()
        )
            .enqueue(object : ApolloCall.Callback<GetUserQuery.Data>() {

                override fun onResponse(response: Response<GetUserQuery.Data>) {
                    if (!response.hasErrors()) {
                        // Here response().data() contains the data you requested
                    } else {
                        Log.d(TAG, "Request Failure ${response.errors()}")
                    }
                }

                override fun onFailure(e: ApolloException) {
                    e.printStackTrace()
                }
            })

That’s about it!

Now that we have taken the first step into GraphQL world let’s dive deeper into some real-world use cases into the Part II of this series.

Bonus tip: Before you are writing any new query/mutation, just update the GraphQL schema.json and see if the existing .graphql files compile or not. As GraphQL codegen all the classes at compile time and does not state which file is causing the validation failure.

While writing this article I have found this cool GraphQL plugin for Android Studio which will help you with code completion and validation errors. To setup the plugin you need to create a config file named .graphqlconfig in the same folder where you have kept schema.json and .graphql files.

{
    "name": "Demo App GraphQL Schema",
    "schemaPath": "schema.json",
    "extensions": {
        "endpoints": {
            "Default GraphQL Endpoint": {
                "url": "http://192.168.0.123:2000/graphql",
                "headers": {
                    "user-agent": "JS GraphQL"
                },
                "introspect": true
            }
        }
    }
}