.graphql file

In this section, we will learn more about GraphQL Queries and integrate with the android app UI.

Create .graphql files with your queries or mutations

Apollo android generates code from queries and mutations contained in .graphql files in your target. Let's define a graphql query to fetch the required data. We define all our queries and mutations in api.graphql file.

Create a new file at the graphql folder api.graphql and add the following code:

githubapi.graphql
+ query getMyTodos {
+ todos(where: { is_public: { _eq: false} }, order_by: { created_at: desc }) {
+ id
+ title
+ created_at
+ is_completed
+ }

We have now written the graphql query that will be converted to a class by apollo codegen that you can use inside your view controller files. Try building your project, there will bunch of code generated for you by apollo.

What does this query do?

The query fetches todos with a simple condition; is_public must be false. We sort the todos descending by its created_at time according to the schema. We specify which fields we need for the todos node.

The query is now ready, let's integrate it with our android code, open TaskFragment.kt

import com.apollographql.apollo.ApolloCall
import com.apollographql.apollo.api.Response
import com.apollographql.apollo.exception.ApolloException
import com.apollographql.apollo.fetcher.ApolloResponseFetchers

also define the query variable which will use the class generated by apollo,

+ private lateinit var getMyTodosQuery: GetMyTodosQuery

Now at the bottom of the file, add this,

// Queries & Mutations
private fun getMyTodoQueryCloud() {
// Init Query
getMyTodosQuery = GetMyTodosQuery.builder().build()
// Apollo runs query on background thread
Network.apolloClient.query(getMyTodosQuery)?.enqueue(object : ApolloCall.Callback<GetMyTodosQuery.Data>() {
override fun onFailure(error: ApolloException) {
Log.d("Todo", error.toString() )
}
override fun onResponse(@NotNull response: Response<GetMyTodosQuery.Data>) {
// Changing UI must be on UI thread
Log.d("Todo", response.data().toString() )
}
})
}

We are using the static apolloClient that we created in our network class so, we have the access to same instance everywhere. Let's log the response for now and initialize the query oncreate of the fragment,

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
completeStatus = it.getString(COMPLETE_STATUS)
}
+ // Get Initial Todos from cloud
+ getMyTodoQueryCloud()
}

Let's remove the mock todos data which was used to populate sample data.

var listItems: MutableList<Task> = mutableListOf(
- Task(1, "Private Task", false),
- Task(2, "Private Task 1", false),
- Task(3, "Private Task 2", false),
- Task(4, "Private Task 3", false),
- Task(5, "Private Task 4", true),
- Task(6, "Private Task 5", false)
)

Woot! You have written your first GraphQL integration with android. Easy isn't it?

How does this work?

When you execute apolloClient.query, Apollo will give callback on its execution,

onFailure: A runtime error with graphQLErrors and networkError properties. Contains information about what went wrong with your query.

onResponse: An object (response.data()) containing the result of your GraphQL query. This will contain our actual data from the server. In our case, it will be the todo data.

You can read more about reponse format and error handling here

Using the data() object, we are parsing the results from the server. In our query, data() object has an array todos which can be mapped to render our RecyclerView in our fragment.

Lets plug this with the list, add below in the OnResponse callback

override fun onResponse(response: Response<GetMyTodosQuery.Data>) {
// Changing UI must be on UI thread
Log.d("Todo", response.data().toString() )
+ listItems = response.data()?.todos()?.toMutableList()
+ activity?.runOnUiThread { updateTabs() }
}

If you noted, there has been some client side filtering to the todos that are displayed.