/
Launch Apollo Studio

Queries


Fetching data in a simple, predictable way is one of the core features of Apollo Android. In this guide, you'll learn how to Query GraphQL data and use the result in your android application. You'll also learn how Apollo-android Client simplifies your data management code by tracking different error states for you.

This page assumes some familiarity with building GraphQL queries. If you'd like a refresher, we recommend reading this guide and practicing running queries in GraphiQL. Since Apollo queries are just standard GraphQL, anything you can type into the GraphiQL query explorer can also be put into .graphql files in your project.

The following examples assume that you've already set up Apollo Android for your Android/Java application. Read our getting started guide if you need help with either of those steps.

All code snippets are taken from the apollo-sample project and can be found here.

Apollo-android takes a schema and a set of .graphql files and uses these to generate code you can use to execute queries and access typed results.

All .graphql files in your project (or the subset you specify as input to apollo-codegen if you customize the script you define as the code generation build phase) will be combined and treated as one big GraphQL document. That means fragments defined in one .graphql file are available to all other .graphql files for example, but it also means operation names and fragment names have to be unique and you will receive validation errors if they are not.

Creating queries

Queries are represented as instances of generated classes conforming to the GraphQLQuery protocol. Constructor arguments can be used to define query variables if needed. You pass a query object to ApolloClient#query(query) to send the query to the server, execute it, and receive results.

For example, if you define a query called FeedQuery:

query FeedQuery($type: FeedType!, $limit: Int!) {
  feedEntries: feed(type: $type, limit: $limit) {
    id
    repository {
      name
      full_name
      owner {
        login
      }
    }
    postedBy {
      login
    }
  }
}

Here, query is the operation type and FeedQuery is the operation name. Apollo-android will generate a FeedQuery class that you can construct (with variables) and pass to ApolloClient#query(query):

apolloClient().query(feedQuery)
        .enqueue(object: ApolloCall.Callback<FeedQuery.Data>() {
             override fun onFailure(e: ApolloException) {
                 Log.i(TAG, response.toString());
             }

             override fun onResponse(response: Response<UpvotePost.Data>) {
                 Log.e(TAG, e.getMessage(), e);
             }
         }, uiHandler);

By default, Apollo will deliver query results on a background thread. You can provide a handler in enqueue, or use apollo-android-support if you're using the result to update the UI.

The ApolloCall.Callback also provides error handling methods for request parsing failed, network error and request cancelled, amongst others.

In addition to the data property, response contains an errors list with GraphQL errors (for more on this, see the sections on error handling and the response format in the GraphQL specification).

Typed query results

Query results are defined as nested immutable classes that at each level only contain the properties defined in the corresponding part of the query definition. This means the type system won't allow you to access fields that are not actually fetched by the query, even if they are part of the schema.

For example, given the following schema:

enum Episode { NEWHOPE, EMPIRE, JEDI }

interface Character {
  id: String!
  name: String!
  friends: [Character]
  appearsIn: [Episode]!
 }

 type Human implements Character {
   id: String!
   name: String!
   friends: [Character]
   appearsIn: [Episode]!
   height(unit: LengthUnit = METER): Float
 }

 type Droid implements Character {
   id: String!
   name: String!
   friends: [Character]
   appearsIn: [Episode]!
   primaryFunction: String
}

And the following query:

query HeroAndFriendsNames($episode: Episode) {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}

Apollo Android will generate a typesafe model looking like this (details are omitted to focus on the class structure):

class HeroAndFriendsNamesQuery {
  data class Data(val hero: Hero)
  data class Hero(val name: String, friends: List<Friend>)
  data class Friend(val name: String)
}

You can fetch results data using the following code. Apollo will parse the response and expose a typesafe model:

val heroAndFriendsQuery = HeroAndFriendsNames(episode = NEWHOPE)

apolloClient().query(heroAndFriendsQuery)
    .enqueue(object: ApolloCall.Callback<HeroAndFriendsNames.Data>() {
         override fun onResponse(response: Response<HeroAndFriendsNames.Data>) {
             Log.i(TAG, response.data?.hero?.name);
         }

         override fun onFailure(e: ApolloException) {
             Log.e(TAG, e.getMessage(), e);
         }
     }, uiHandler);
}

Because the above query won't fetch appearsIn, this property is not part of the returned result type and cannot be accessed here.

Edit on GitHub