There are a number of ways in which Android and iOS development is “converging” at the moment but I think the most exciting area
is the adoption of Declarative UI frameworks on both platforms -SwiftUI
on iOS and Jetpack Compose
on Android. As such,
my interest is always piqued, when I see tweets like following from Thomas Ricouard, by what would be involved in creating a Jetpack Compose version of a project like this.
An added interest in this case is the use of GraphQL
and also saw this as an opportunity to try out the
Apollo GraphQL library (and, for bonus points, it’s Kotlin Multiplatform support!).
The code shown here is included as part of MortyComposeKMM project on Github.
I’ve published a new open source project for anyone curious about GraphQL + SwiftUI. All the code of this very simple app is accessible on Github and its only purpose is to play with GraphQL. https://t.co/tNiXkq44au
— Thomas Ricouard (@Dimillian) December 21, 2020
GraphQL
So, GraphQL is described here as
a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API
In general it’s seen as an alternative to “traditional” REST APIs that gives more control over content returned and a mechanism to obtain schema of that content…from which, as we’ll see later, strongly typed client APIs can be generated. The server we’re going to interact with in this project is https://rickandmortyapi.com/graphql (BTW the web page at this url also provides a way to interactively try out different queries).
The following is GraphQL query for example for retrieving list of the show’s characters from the endpoint.
Apollo GraphQL
The way we’re going to interact with our GraphQL server in this case is through use of the Apollo library, described as a “strongly-typed, caching GraphQL client for the JVM, Android and Kotlin multiplatform”
Joe Birch wrote a really nice article recently on getting started wth Apollo GraphQL on Android that covers a lot of details on how to set it up so will just mention below a number of the specific steps needed for this project. Also, in our case we’re using Apollo’s Kotlin Multiplatform support and have followed some of instructions related to that.
So, having added the Apollo gradle plugin and related dependencies to our shared Kotlin Multiplatform module we can now run following to retrieve schema.json
for the endpoint we’re interacting with.
We copy this file along with our .graphql
query file(s) to shared/src/commonMain/graphql/
folder (see Queries.graphql
in repository to see
the queries we’re using…the GetCharacters
one was shown earlier). Now, when we build the shared module, source code is generated which allows
us to interact with the endpoint. Using this code we can now create something like MortyRepository
class as shown below where we
instantiate ApolloClient
object and use it to make various queries.
Compose Paging library
The above GraphQL queries support pagination and this plays very well with use of Compose’s Paging library.
We can now create PagingSource
such as following that invokes APIs in our MortyRepository
.
Our ViewModel
then returns a Flow
representing the paged data.
And, finally, we can use Compose Paging Library’s collectAsLazyPagingItems()
to collect values which we can show in the list (Note we’re also
using Koin
to inject view model dependency in our Composable function). Now as we scroll down through the list, the data is automatically retrieved
from endpoint as needed.
And this is what our UI looks like….on Android:
and on iOS (using same GraphQL queries in shared Kotlin Multiplatform code):
Featured in Kotlin Weekly Issue #230, Android Weekly Issue #446 and GraphQL Weekly Issue #218
Related tweet
Jetpack Compose and GraphQL, a very merry combination! https://t.co/kJClK07x48
— John O'Reilly (@joreilly) December 22, 2020
Wrote an article about this effort (sorry for title, was trying to incorporate something "seasonal" 😀 🤶) https://t.co/i6PPy27uky