Unleashing the Power of GraphQL in Android Development with Apollo

Unleashing the Power of GraphQL in Android Development with Apollo

ยท

3 min read

If you've ever felt constrained by REST APIs or struggled with inefficient data retrieval, GraphQL might come to shake things up.

What's the Buzz About GraphQL?

Picture this: You're knee-deep in your company project, and every time you need new data from the server, it's like pulling teeth. Endless meetings with the architecture team, waiting for new endpoints to be approved, and even then, you often find yourself cobbling together data from multiple endpoints just to get what you need. Sound familiar? Unlike traditional REST APIs, where each endpoint serves up a predefined set of data, GraphQL gives you the power to request exactly what you need, when you need it, all in a single query. No more waiting for new endpoints to be created or juggling multiple requests โ€“ with GraphQL, you're in control.

To apply GraphQL in an Android project, there are different options but I will concentrate in Apollo for this post as it has type-safe way to interact with your GraphQL API, with features like query caching and automatic data fetching.

Let's dive deep into a real-life example: I have a transportation app, and I need to fetch route information from our server but the current endpoints return all the route data object, however, I only care about specific fields of the route like the name, id, and stop list information like name, id and coordinates.

The first thing to do is to add the Apollo gradle dependency. I am using android Catalogs to declare my dependencies, it looks like this:

implementation(libs.apollo)
apollo = {group = "com.apollographql.apollo", name = "apollo-runtime", version.ref = "apolloVersion"}
apolloVersion = "3.6.0"

Our next step is to define the contract for what we are going to be quering to the server.
I am using MVI with Clean architecture so I created a queries.graphql file in the data module. The content of the file is the scheme of our contract:

type Route {
id: ID!
name: String!
stops: [Stop!]!
}

type Stop {
id: ID!
name: String!
coordinates: Coordinates!
}

type Coordinates {
latitude: Float!
longitude: Float!
}

type Query {
route(id: ID!): Route
}

Out of the box, Apollo offers a quick way to convert this grapghql queries into kotlin/java code for Android to execute, handle and parsing the data.These generated classes include:

  • Data classes representing the GraphQL types defined in your schema.

  • Query classes representing your GraphQL queries.

  • Response classes representing the structure of the data returned by your queries.

Run the Apollo CLI command in your project directory terminal to generate the necessary classes:

npx apollo codegen:generate --androidb

Let's create our firts query now. It should look like this:

query GetRoute($routeId: ID!) {
    route(id: $routeId) {
        id
        name
        stops {
            id
            name
            coordinates {
                latitude
                longitude
            }
        }
    }
}

Finally, we can integrate this query now as we usually do with any rest api request.

import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.coroutines.toFlow
import com.apollographql.apollo.exception.ApolloException
import com.example.generated.GetRouteQuery
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect

class RouteRemoteDataSource(private val apolloClient: ApolloClient) {

    suspend fun getRoute(routeId: String): Flow<Result<GetRouteQuery.Route>> {
        return apolloClient.query(GetRouteQuery(routeId))
            .toFlow()
            .catch { e ->
                emit(Result.failure<GetRouteQuery.Route>(ApolloException("Failed to fetch route", e)))
            }
            .collect { response ->
                val route = response.data?.route
                if (route != null) {
                    emit(Result.success(route))
                } else {
                    emit(Result.failure(ApolloException("Route not found")))
                }
            }
    }
}

As you can see, this is much simpler than parsing a huge JSON model where we might need to ignore most of the properties. By leveraging GraphQL with Apollo Android, we can create more efficient, flexible, and maintainable Android apps, delivering exceptional user experiences. Happy coding! ๐Ÿš€

ย