This version is planned to be the last beta of Apollo Android 3 before a release candidate ๐. It mainly focuses on stabilization and tweaks to the public API, makes it easier to work with the Java9 module system, and fixes a few issues.
Before going stable, we tweaked the public API to ensure consistency. The following methods have been renamed:
| Before | After |
|---|---|
ApolloClient.mutate() | ApolloClient.mutation() |
ApolloClient.subscribe() | ApolloClient.subscription() |
ApolloSubscriptionCall.execute() | ApolloSubscriptionCall.toFlow() |
In order to better support Java 9 and remove split packages, the following classes have been moved:
| Before | After |
|---|---|
com.apollographql.apollo3.cache.ApolloCacheHeaders | com.apollographql.apollo3.cache.normalized.api.ApolloCacheHeaders |
com.apollographql.apollo3.cache.CacheHeaders | com.apollographql.apollo3.cache.normalized.api.CacheHeaders |
com.apollographql.apollo3.cache.CacheHeaders.Builder | com.apollographql.apollo3.cache.normalized.api.CacheHeaders.Builder |
com.apollographql.apollo3.cache.CacheHeaders.Companion | com.apollographql.apollo3.cache.normalized.api.CacheHeaders.Companion |
com.apollographql.apollo3.cache.normalized.CacheKey | com.apollographql.apollo3.cache.normalized.api.CacheKey |
com.apollographql.apollo3.cache.normalized.CacheKey.Companion | com.apollographql.apollo3.cache.normalized.api.CacheKey.Companion |
com.apollographql.apollo3.cache.normalized.CacheKeyResolver | com.apollographql.apollo3.cache.normalized.api.CacheKeyResolver |
com.apollographql.apollo3.cache.normalized.CacheResolver | com.apollographql.apollo3.cache.normalized.api.CacheResolver |
com.apollographql.apollo3.cache.normalized.DefaultCacheResolver | com.apollographql.apollo3.cache.normalized.api.DefaultCacheResolver |
com.apollographql.apollo3.cache.normalized.FieldPolicyCacheResolver | com.apollographql.apollo3.cache.normalized.api.FieldPolicyCacheResolver |
com.apollographql.apollo3.cache.normalized.NormalizedCache.Companion | com.apollographql.apollo3.cache.normalized.api.NormalizedCache.Companion |
com.apollographql.apollo3.cache.normalized.NormalizedCacheFactory | com.apollographql.apollo3.cache.normalized.api.NormalizedCacheFactory |
com.apollographql.apollo3.cache.normalized.ReadOnlyNormalizedCache | com.apollographql.apollo3.cache.normalized.api.ReadOnlyNormalizedCache |
com.apollographql.apollo3.cache.normalized.Record | com.apollographql.apollo3.cache.normalized.api.Record |
com.apollographql.apollo3.cache.normalized.RecordFieldJsonAdapter | com.apollographql.apollo3.cache.normalized.api.RecordFieldJsonAdapter |
com.apollographql.apollo3.cache.normalized.MemoryCache | com.apollographql.apollo3.cache.normalized.api.MemoryCache |
com.apollographql.apollo3.cache.normalized.MemoryCacheFactory | com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory |
com.apollographql.apollo3.cache.normalized.OperationCacheExtensionsKt | com.apollographql.apollo3.cache.normalized.api.OperationCacheExtensionsKt |
Other renames
| Before | After |
|---|---|
com.apollographql.apollo3.api.ApolloExperimental | com.apollographql.apollo3.annotations.ApolloExperimental |
com.apollographql.apollo3.api.ApolloInternal | com.apollographql.apollo3.annotations.ApolloInternal |
com.apollographql.apollo3.cache.normalized.ObjectIdGenerator | com.apollographql.apollo3.cache.normalized.api.CacheKeyGenerator |
com.apollographql.apollo3.cache.normalized.ObjectIdGeneratorContext | com.apollographql.apollo3.cache.normalized.api.CacheKeyGeneratorContext |
com.apollographql.apollo3.network.http.OkHttpEngine | com.apollographql.apollo3.network.http.DefaultHttpEngine |
ApolloClient's mutate and subscribe methods have been renamed to mutation and subscription respectively. This
creates a more consistent API by reusing the GraphQL specification terminology.
Also, mutate(), subscribe() could be misleading as despite being verbs, no action is done until execute() is
called. Using mutation()/subscription() hints that execute() is required as a terminal operation.
// Before
val data = client.mutate(MyMutation()).execute()
// After
val data = client.mutation(MyMutation()).execute()
Also, ApolloSubscriptionCall.execute() has been renamed to ApolloSubscriptionCall.toFlow() to make it clearer that it
returns a cold Flow that can be collected several times:
// Before
val flow = client.subscription(MySubscription).execute()
// After
val flow = client.subscription(MySubscription).toFlow()
CacheKeys were sometimes referred to as Cache ids, Object ids, despite all of them being the same concept (the key
of an object in the cache). For consistency inside the Apollo Android codebase and with the iOS and Web
clients, CacheKey is going to be used everywhere moving forward
// Before
val objectIdGenerator = object : ObjectIdGenerator {
override fun cacheKeyForObject(obj: Map<String, Any?>, context: ObjectIdGeneratorContext): CacheKey? {
// Retrieve the id from the object itself
return CacheKey(obj["id"] as String)
}
}
val apolloClient = ApolloClient.Builder()
.serverUrl("https://...")
.normalizedCache(
normalizedCacheFactory = cacheFactory,
objectIdGenerator = objectIdGenerator,
)
.build()
// After
val cacheKeyGenerator = object : CacheKeyGenerator {
override fun cacheKeyForObject(obj: Map<String, Any?>, context: CacheKeyGeneratorContext): CacheKey? {
// Retrieve the id from the object itself
return CacheKey(obj["id"] as String)
}
}
val apolloClient = ApolloClient.Builder()
.serverUrl("https://...")
.normalizedCache(
normalizedCacheFactory = cacheFactory,
cacheKeyGenerator = cacheKeyGenerator,
)
.build()
dataAssertNoErrors (#3534)To reflect more accurately what this method does, dataOrThrow is now dataAssertNoErrors.
Apollo Android can either generate GraphQL enums as Kotlin enums or sealed classes. In previous 3.0 releases, the
default was to generate sealed classes but it is now enums, as this will be more expected, works better with Swift, and
is consistent with the 2.x behavior. To fallback to the previous behaviour of always generating sealed classes, use the sealedClassesForEnumsMatching Gradle option:
apollo {
sealedClassesForEnumsMatching.set(listOf(".*"))
}
Using Apollo Android from Java should be less cumbersome thanks to a few API tweaks in this release. For example, to set up a normalized cache:
// Before
builder = ClientCacheExtensionsKt.normalizedCache(
builder,
new MemoryCacheFactory(10 * 1024 * 1024, -1),
TypePolicyObjectIdGenerator.INSTANCE,
FieldPolicyCacheResolver.INSTANCE,
false
);
// After
NormalizedCache.configureApolloClientBuilder(
builder,
new MemoryCacheFactory(10 * 1024 * 1024, -1),
);
HttpNetworkTransport and WebSocketNetworkTransport now use the Builder pattern for instantiationFlowDecorator have been removed from ApolloClient as ApolloInterceptor can be used insteadhttpHeader extension is now addHttpHeaderApollo Android now publishes jar files containing the Automatic-Module-Name property and non-split packages. This
change makes it easier to work with Apollo Android from a Java 9+ modularized application.
You no longer need to register any of the built-in adapters after declaring a custom scalar type that maps to a built-in type (Int, Long, String, etc.).
For instance, when declaring this custom scalar type:
apollo {
customScalarsMapping = [
"MyCustomNumber": "kotlin.Long"
]
}
There is no need to call addCustomScalarAdapter on the builder anymore, as since it is for a kotlin.Long it will
automatically fall back to the built-in LongAdapter.
Fetched April 11, 2026