ApolloStore


Apollo Kotlin exposes the ApolloStore API to read and write from the normalized cache programmatically. The ApolloStore sits on top of NormalizedCache, exposes a thread safe API as well as methods that make it easier to read and write fragments and operations.

The store is accessible with the ApolloClient.apolloStore extension:

Kotlin
1val apolloClient = ApolloClient.Builder()
2  .serverUrl("https://example.com/graphql")
3  .normalizedCache(MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024))
4  .build()
5
6val apolloStore: ApolloStore = apolloClient.apolloStore

Note that the read and write operations are synchronous and might block if the underlying cache is doing IO (such as the SQLite cache). Therefore calling them from the main thread should be avoided.

Reading operation data

Just like a regular GraphQL query, the main way to use the store is to read and write queries:

Given the following query:

GraphQL
1query GetBook($id: String!) {
2  book(id: $id) {
3    title
4    author {
5      name
6    }
7  }
8}

You can read it like this:

Kotlin
1val data = apolloClient.apolloStore.readOperation(GetBookQuery(id = "42"), apolloClient.customScalarAdapters)
2
3println("Title=${data.title}")
4println("Author Name=${data.author.name}")

In the event of cache miss, readOperation will throw:

Kotlin
1try {
2  apolloClient.apolloStore.readOperation(GetBookQuery(id = "42"), apolloClient.customScalarAdapters)
3} catch(e: CacheMissException) {
4  println("CacheMiss on key: ${e.key}.${e.fieldName}")
5}

If you declared scalar adapters at runtime, pass your client's customScalarAdapters to the store's methods, as the store will need them to convert scalar values to and from their Kotlin/Java types.

Writing operation data

Writing operation data is similar to reading:

Kotlin
1apolloClient.apolloStore.writeOperation(GetBookQuery(id = "42"), data, apolloClient.customScalarAdapters)

Note how you'll need to pass the data along the operation.

Reading and Writing fragments

In the GraphQL specification, fragments are always part of a larger operation and cannot be executed standalone.

GraphQL
1fragment BookDetails on Book {
2  id
3  title
4  author {
5    name
6  }
7}

Apollo Kotlin makes an exception to that rule and allows to read/write individual fragments. This is disabled by default and can be enabled with generateFragmentImplementations:

Kotlin
1apollo {
2  service("service") {
3    generateFragmentImplementations.set(true)
4  }
5}

Because fragments are not rooted, you need to specify the root cache id of the fragment:

Kotlin
1val data = apolloClient.apolloStore.readFragment(BookDetailsImpl(), CacheKey("42"), apolloClient.customScalarAdapters)
2
3println("Title=${data.title}")
4println("Author Name=${data.author.name}")

Fragments can contain variables. Different fragments with different variables can return different data. In that case the fragment Impl class will require variables as constructor parameters:

GraphQL
1fragment BookDetails on Book {
2  id
3  title(locale: $locale)
4}
Kotlin
1val data = apolloClient.apolloStore.readFragment(BookDetailsImpl(locale = "en-US"), CacheKey("42"), apolloClient.customScalarAdapters)
2
3println("Title=${data.title}")

Clearing the cache

Call apolloClient.apolloStore.clearAll() to clear the cache of all entries.

Feedback

Edit on GitHub

Forums