The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Queries and Paging

Sometimes, there is just too much data.

Users of Web browsers are used to the notion of data paging, whether that comes in the form of pages of search engine results, “append as you scroll” patterns for Twitter timelines, or in other forms.

For data sets known to be potentially large, Web service APIs often offer paging, where clients can indicate a starting point and a number of items to retrieve from the Web service. GraphQL-powered Web services are no exception. In particular, there is one convention for implementing such paging, promoted by the Relay project for Web clients. Since having a Relay-compatible GraphQL server is often an objective, the Relay paging convention has become fairly popular.

In this chapter, we will explore this convention, what it looks like from a GraphQL standpoint, and how to consume this sort of page-at-a-time results from an Apollo-Android client.

Taking a Page from GitHub

GitHub’s GraphQL API makes use of paged queries quite a bit, in part because GitHub has geared its API to handle arbitrarily complex scenarios, including huge projects with lots of contributors and tons of code.

So, let’s start by invoking a GitHub paged query to get the first page of results.

Starring Some Repositories

The specific query that we are going to invoke retrieves the starredRepositories field for the viewer. As the name suggests, starredRepositories represents repositories starred by the logged-in user.

To make this query be effective — both for interactive exploration and for use with this chapter’s sample app — it will help if you have a bunch of starred repositories. Ideally, you have 11 or more.

You can see your starred repositories from your GitHub profile page, in the “Stars” tab:

GitHub Profile, Showing Starred Repositories
Figure 39: GitHub Profile, Showing Starred Repositories

To star a repository, on any GitHub page for that repository, find the button bar towards the top of any GitHub repo page:

GitHub Button Bar
Figure 40: GitHub Button Bar

Click the “Star” button to star it, at which point the button’s caption will change to “Unstar”.

Getting a Page of Results

Once you have some starred repositories, visit the GitHub GraphQL API Explorer and fill in the following GraphQL document in the GraphiQL pane:

query myStars($first: Int, $after: String) {
  viewer {
    login
    starredRepositories(first: $first, after: $after) {
      edges {
        cursor
        node {
          id
          name
        }
      }
      pageInfo {
        hasNextPage
      }
    }
  }
}

Then, in the Query Variables pane, fill in:

{
  "first": 5
}

(we can skip the after variable, as it will default to null, which is what we want here for now)

Then, execute the query using the GraphiQL run button. This should give you a JSON output showing 5 of your starred repositories:

{
  "data": {
    "viewer": {
      "login": "commonsguy",
      "starredRepositories": {
        "edges": [
          {
            "cursor": "Y3Vyc29yOnYyOpHOAC50Bg==",
            "node": {
              "id": "MDEwOlJlcG9zaXRvcnkxNzc2MjA=",
              "name": "em-proxy"
            }
          },
          {
            "cursor": "Y3Vyc29yOnYyOpHOAC50Bw==",
            "node": {
              "id": "MDEwOlJlcG9zaXRvcnkyNTU5MjU=",
              "name": "cwac-task"
            }
          },
          {
            "cursor": "Y3Vyc29yOnYyOpHOAC50CA==",
            "node": {
              "id": "MDEwOlJlcG9zaXRvcnkyNTU5NDI=",
              "name": "cwac-bus"
            }
          },
          {
            "cursor": "Y3Vyc29yOnYyOpHOAC50CQ==",
            "node": {
              "id": "MDEwOlJlcG9zaXRvcnkyNTU5NTA=",
              "name": "cwac-cache"
            }
          },
          {
            "cursor": "Y3Vyc29yOnYyOpHOAC50Cg==",
            "node": {
              "id": "MDEwOlJlcG9zaXRvcnkyNTU5ODE=",
              "name": "cwac-custmenu"
            }
          }
        ],
        "pageInfo": {
          "hasNextPage": true
        }
      }
    }
  }
}

Examining the Query and Its Results

Given that we can get our first page’s worth of starred repositories, let’s break down the GraphQL query and the results that we got back.

The Viewer

As outlined in the previous chapter, GitHub uses the viewer pattern as part of its authentication and authorization approach. Your GitHub API key grants you access to whatever the viewer field offers to you. In the previous chapter’s samples, we just retrieved the login field from viewer. Here, we are also requesting the starredRepositories field.

The starredRepositories

GitHub’s starredRepositories field follows the Relay Cursor Connections Specification.

Specifically starredRepositories is a list of StarredRepositoryConnection objects, fulfilling one of the Relay specification’s requirements: paged queries return objects whose type names end in Connection.

Typically, such fields will have arguments that indicate what “page” of results should be returned. Sometimes, the GraphQL endpoint will require such fields. GitHub’s does not — if you remove the variables from your query and run it again, you should get back all of your starred repositories, not just 5.

However, originally, we used one of those arguments: first, indicating how many items we want back in the results. Why this is named first and not something like pageSize or count will become a bit clearer as we proceed.

The Edges

Relay-style Connection types have two required fields. The first of these is edges, and it must return what the Relay specification refers to as an “edge type”. That is some object with its own pair of required fields: cursor and node.

cursor is an opaque string… at least in terms of how it is represented in the JSON (and therefore in the client-side code). The server is welcome to define it as something else (e.g., a scalar), but clients can safely assume that it will be a string. Here, “opaque” means “do not make any assumptions about the nature of its value”. We will see shortly where and how we use this value.

The node returns the actual data associated with this entry. In the case of starredRepositories, a node is a Repository object, which has lots of fields for details about that GitHub repository. We happen to be retrieving the repository’s id and name.

An edge can contain additional fields beyond these two. In the case of starredRepositories, the edge also has a starredAt field, indicating the DateTime when you starred that repository.

The Page Info

The pageInfo field will be an object with metadata about this page’s worth of results. The Relay specification requires it to have at least two fields: hasPreviousPage and hasNextPage. As one might expect, these are boolean values, indicating whether we can move forwards or backwards from the current page.

However, only one of the two will be relevant for any given query. In our case, we are using first to indicate how many starred repositories we want, and according to the Relay specification, only hasNextPage needs to hold a meaningful value. hasPreviousPage will be defined but will always be false.

In our case, we requested fewer starred repositories (5) that existed, and so the result for hasNextPage is true.

We will see both of these fields in use in the next section.

Please, GitHub, Can I Have Some More?

The preview of this section was traded for a bag of magic beans.

Paging with Apollo-Android

The preview of this section was traded for a bag of magic beans.