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:
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:
1query GetBook($id: String!) {
2 book(id: $id) {
3 title
4 author {
5 name
6 }
7 }
8}
You can read it like this:
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:
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:
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.
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
:
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:
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:
1fragment BookDetails on Book {
2 id
3 title(locale: $locale)
4}
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.