This release contains a handful of bug fixes and improvements.
ApolloCompilerPlugin.schemaListener()The compiler plugins API has been extended to allow listening to schema changes.
This can be used to have plugins generate code based on the schema. To do this, implement the schemaListener
function on your plugin:
class MyCompilerPlugin() : ApolloCompilerPlugin {
@ApolloExperimental
override fun schemaListener(): SchemaListener {
return object : SchemaListener {
override fun onSchema(schema: Schema, outputDirectory: File) {
// Generate some code inside outputDirectory based on schema
}
}
}
}
Previously, to map a scalar to a generic type, you had to use a typealias.
Now, simple generic types are accepted, and common types like List and String don't need to be fully qualified:
mapScalar("MassList", "List<com.example.Measure<com.example.Mass>>", "com.example.MassListAdapter")
Many thanks to @ebrattli, @agrosner and @cvb941 for their contributions to this release 💙!
"operationOutput" and ./gradlew downloadApolloSchema (#6097)registerJavaGeneratingTask (#6149)field (#6093)ResolverKey fails (#6136)@nonnull (#6152)JsonNumber in MapJsonReader (#6141)JsonNumber in Record (#6139)Apollo Kotlin 4 is a maturity release. It focuses on tooling, stability and making the library more maintainable, so it can evolve smoothly for the many years to come.
While most of the core APIs stayed the same, Apollo Kotlin 4 contains a few binary breaking changes. To account for that, and in order to be more future-proof, we changed the package name to com.apollographql.apollo.
You need to replace all the com.apollographql.apollo3 with com.apollographql.apollo in your codebase.
Thanks again to everyone who provided feedback during the alphas/betas.
@oneOf (GraphQL RFC)@semanticNonNull and @catch (doc)@semanticNonNullField@defer support does not work with AutoPersistedQueryInterceptor@typePolicy on unions@link imports for used kotlin_labs directives@oneOf for Input Objects@include directive on a fragment@catch & partial data@typePolicy defined for nonexistant field.@defer@nonull could have surprising effects in error casesWe're on the road to v4 with this second release candidate which includes a few minor tweaks as well as one new feature.
Note: in v4.0.0-rc.1 apollo-debug-server and apollo-tooling depended on com.apollographql.apollo3 artifacts. This is no longer the case with v4.0.0-rc.2, where all dependencies are under the com.apollographql.apollo group id.
.memoryCacheOnly(true) can be set on calls to read and store records in the memory cache only even when a persistent cache is configured.
This can be useful in scenarios where long term storage isn't needed and performance is important.
ApolloCompilerPlugin (#6059)Version 3.8.5 is a maintenance release. New developments happen in the 4.x versions.
We changed the package name from com.apollographql.apollo3 to com.apollographql.apollo for version 4. This is a safe default for the many years to come and works well with our new evolution policy.
If you are updating from version 3 or an alpha/beta version 4, you need to replace all com.apollographql.apollo3 with com.apollographql.apollo
As part of this release, some of the non-core artifacts have been moved to separate coordinates and GitHub repositories. Moving forward, this will allow us to iterate faster on those artifacts while keeping the core ones more maintainable.
Some of the existing symbols are kept as deprecated to ease the transition (like MockServer for an example). Others (the -incubating ones) have been removed, and you need to update them now.
You can read more in the migration guide.
com.apollographql.apolloSync to avoid them taking precedence over their suspend counterparts (#5976)gradle/actions/setup-gradle instead of gradle-build-action (#5981)ApolloCompilerPluginProvider is introduced to allow passing arguments to compiler plugins. See the compiler plugins documentation for more details.[testing] Use com.apollographql.mockserver.MockServer (#5939)
[testing] Simplify our implementation of runTest (#5935)
[testing] Prepare apollo-testing-support to new MockServer (#5934)
[runtime] Remove multidex library (#5930)
[all] Bump languageVersion/apiVersion to Kotlin 2.0 (#5931)
[codegen] fix mapping of the builtin Float type (#5928)
[IJ Plugin] Add inspection to warn about the presence of a GraphQL config file (#5908)
[codegen] Add a null-check to java enum safeValueOf (#5904)
[gradle-plugin] Remove eager configuration (#5923)
[gradle-plugin] sort input files (#5919)
[IJ Plugin] Suppress GraphQLDuplicateDirective for certain directives (#5910)
[adapters] Add KtorHttpUrlAdapter (#5915)
[IJ Plugin] Add a "new UI" compatible icon (#5906)
[IJ Plugin] Operation and fragment definition rename (#5912)
[IJ Plugin] Add @link directives to extra.graphqls during v3->v4 migration (#5909)
[IJ Plugin] Remove GraphQL IJ plugin issue workaround (#5907)
[cache] Pagination: use "field key" instead of "field name" (#5898)
[IJ Plugin] Improve the presentation of GraphQL elements when navigating to them (#5900)
[IJ Plugin] Include subfolders when contributing GraphQL config (#5871)
[runtime] Remove existing interceptors from ApolloClient.Builder before adding new ones (#5858)
[codegen] Add ApolloCompilerPluginProvider (#5865)
[runtime] Clear current ApolloStore related interceptors when calling .store() on builder (#5857)
[cache] Call through to loadRecords from the MemoryCache to the SQL one (#5848)
[runtime] deprecate operationIdGenerator (#5850)
Version 3.8.4 is a maintenance release with one bug fix and 2 performance improvements. New developments happen in the 4.x versions.
ApolloClient.Builder.okHttpClient() returns null instead of this (#5860)If you're using a chained memory + SQL cache, #5840 makes sure cache writes are wrapped in a transaction, making them much faster.
Plugin is renamed to ApolloCompilerPlugin. There is a new documentTransform API as well as other fixes. More details in the compiler plugins documentation.
A new .websocket package is available that makes it easier to retry WebSockets and handle errors. More details and migration guide in the experimental websockets documentation.
We recommend using reactive patterns to test your UI instead. See this article about ways to do so.
androidx.startup was introduced in beta.5 but is problematic for unit tests and other cases. beta.6 removes that dependency. More details in the network connectivity documentation.
You can see Wasm in action at https://wasm.confetti-app.dev/
In a effort to minimize the number of thread switches, the whole request is now run in the same dispatcher. See Threading.md for more details.
Many thanks to @joreilly, @ychescale9 and @japhib for their contributions to this release 💙!
Plugin to ApolloCompilerPlugin and add error message for bad configurations (#5821)@ApolloEnumConstructor and make enum as sealed class Unknown constructor opt-in (#5813)isOnline to a suspend funApolloClient with lazily initialized Call.Factory. (#5784)androidx.startup dependency (#5761, #5720)Version 3.8.3 is a maintenance release with two new convenience APIs and a Kotlin update. New developments happen in the 4.x versions.
Note: because Apollo Kotlin now depends on kotlin-stdlib version 1.9, you need the 1.8+ Kotlin compiler to compile your project.
ApolloClient.Builder(ApolloHttpCache) (#5638) (#5640)buildPostBody to write operation extensions (#5631).exception (#5018)IOException when calling ApolloHttpCache.remove (#5730)PackageNameGenerator and OperationOutputGenerator are deprecated. See the documentation page about Apollo compiler plugins for more details.@semanticNonNull or @catch you should bump your @link directives to use 0.3. See the nullability documentation page for more details.https://go.apollo.dev/ij-plugin-snapshots to get the latest weekly snapshots. (#5600)Many thanks to @ribafish, @molundb, @mboyd1993, @rohandhruva and @baconz for their help in this release 💙!
NetworkMonitor (#5690)ApolloClient.retryOnError(Boolean) (#5685)@catch on fieldDefinitions, interfaces and objects (#5623)X-APOLLO-OPERATION-NAME, X-APOLLO-OPERATION-ID and the multipart boundary (#5533)generateAsInternal code (#5526)4.0.0-beta.3 (#5452)This release adds initial support for WebAssembly by adding the wasmJs target.
Executing queries/mutations is working but this target is experimental (Kotlin/Wasm is Alpha) and has multiple limitations:
Downloading a schema from introspection (./gradlew downloadServiceSchemaFromIntrospection) got broken in the previous release (#5449) and is now fixed.
Many thanks @chris-hatton and @sdfgsdfgd for contributing this version 💙
⚠️ we're aware of a regression in downloadApolloSchema, we'll make a new release soon.
The normalized cache viewer can now display the contents of your in-memory cache. To do so, it relies on a debug server that you need to run in your debug builds:
val apolloClient = ApolloClient.Builder()
.serverUrl("https://example.com/graphql")
.build()
if (BuildConfig.DEBUG) {
ApolloDebugServer.registerApolloClient(apolloClient)
}
You can read more about it in the "Apollo debug server" documentation page.
@catch and @semanticNonNull support@catch makes it possible to model GraphQL errors as FieldResult Kotlin classes giving you inline access to errors:
query GetUser {
user {
id
# map name to FieldResult<String?> instead of stopping the parsing
name @catch
avatarUrl
}
}
@semanticNonNull is a better @nonnull. @semanticNonNull makes it possible to mark a field as null only on error. The matching Kotlin property is then generated as non-null:
# mark User.name as semantically non-null
extend type User @semanticNonNull(field: "name")
Both those directives are experimental and require opt-in of the nullability directives
You can read more about them in the "handle nullability" documentation page.
@oneOf support@oneOf introduces input polymorphism to GraphQL:
input PetInput @oneOf {
cat: CatInput
dog: DogInput
fish: FishInput
}
input CatInput { name: String!, numberOfLives: Int }
input DogInput { name: String!, wagsTail: Boolean }
input FishInput { name: String!, bodyLengthInMm: Int }
type Mutation {
addPet(pet: PetInput!): Pet
}
With @oneOf, only one of cat, dog or fish can be set.
@oneOf support is automatically enabled if your schema has the @oneOf directive definition.
You can read more about it in the @oneOf RFC
[all] @oneOf support (#5394, #5388)
[all] @catch and @semanticNonNull support (#5405)
[all] Take default values into account when computing field cache keys (#5384)
[all] Bump Kotlin to 2.0.0-Beta1 (#5373)
[IJ Plugin] Add 'Input class constructor issue' inspection (#5427)
[IJ plugin] Update v3->v4 migration following API tweaks (#5421)
[IJ Plugin] Report invalid oneOf input object builder uses (#5416)
[IJ Plugin] Add inspection for @oneOf input type constructor invocation (#5395)
[IJ plugin] Make the refresh button work with all normalized cache sources. (#5400)
[IJ Plugin] Cache viewer: take numbers into account in key sorting (#5396)
[IJ Plugin] Bump pluginUntilBuild to 233 (#5377)
[IJ Plugin] Telemetry: don't use a libraries changed listener (#5361)
[IJ Plugin] Cache viewer: add cache size to selector (#5357)
[IJ plugin] Use apollo-debug-server to retrieve normalized caches (#5348)
[IJ plugin] Cache viewer: "Pull from Device" modal dialog instead of action menu (#5333)
[IJ Plugin] Fix v3->v4 migration with ApolloCompositeException (#5330)
[runtime] remove some of the ApolloResponse.Builders (#5426) [runtime] Add a few symbols as ERROR deprecation for the migration (#5422) [runtime] Add executeV3 + toFlowV3 (#5417) [runtime] Revive dataAssertNoErrors (#5419) [runtime] Allow no data and no exception in case of GraphQL errors (#5408) [runtime] Expose ExecutionContext to HttpEngine and add OkHttp helpers (#5383) [runtime] Improve deprecation messages (#5411) [runtime] Go back to just one Adapter class (#5403) [runtime] Fix Optional.getOrElse (#5399)
[compiler] Remove kotlin-labs-0.1 directives (#5404) [compiler] Throw a better exception than NullPointerException if a value is missing (#5402) [compiler] ExecutableValidationResult is returned by validateAsExecutable() and cannot be @ApolloInternal (#5406) [compiler] Rework the IrType hierarchy (#5392) [compiler] remove CCN (#5387) [compiler] Remove antlr (#5336) [compiler] Tweak description javadoc, there is no need to use the same escaping as Kotlin (#5424)
[mockserver] Support setting port for Apollo MockServer (#5389) [mockserver] Add WebSocket support to the MockServer (#5334) [tools] Implement 2-step introspection (#5371) [apollo-execution] Allow to pass arguments to the root types (#5352) [apollo-ksp] Initial support for interfaces (#5351)
We're continuing to progress towards the stable release of Apollo Kotlin v4 with this 2nd beta, which contains a few bug fixes and a new normalized cache viewer in the IDE plugin.
This is a great time to try out the new version and report any issues you might find!
The IDE plugin now has a graphical tool to inspect a normalized cache database. It lets you browse the records and see their contents. This is useful to debug cache issues, or to understand how the normalized cache works.
The tool is available from View | Tool Windows | Apollo Normalized Cache.
More information about the plugin can be found here.
The first beta of the next major version of Apollo Kotlin is here!
While there still may be a few API changes before the stable release, we are getting close and this is a great time to try out the new version and report any issues you might find!
Many thanks to @baconz and @hbmartin for their awesome contributions to this release!
The GraphQL community is working hard at making it easier to work with nullability in GraphQL.
In Apollo Kotlin, it is now possible to change the nullability of fields and list elements at the schema level using schema extensions. This is useful if you believe the schema made a field nullable for error reasons only and you don't want to handle those errors. In these cases, the whole query will return as an error.
Given the following SDL:
# schema.graphqls
type Query {
random: Int
list: [String]
required: Int!
}
You can extend it like so:
# extra.graphqls
extend type Query {
# make random non-nullable
random: Int!
# make list and list items non-nullable
list: [String!]!
# make required nullable
required: Int
# add a new field
new: Float
}
generateMethods option to control which model methods are generated (#5212)By default all Kotlin models, operations, fragments, and input objects are generated as data classes. This means that the Kotlin compiler will
auto-generate toString, equals hashCode, copy and componentN. If you don't think you need all of those
methods, and/or you are worried about the size of the generated code, you can now choose which methods to generate with the generateMethods option:
apollo {
service("service") {
// Generates equals/hashCode
generateMethods.set(listOf("equalsHashCode"))
// Also generates toString, equals, and hashcode
generateMethods.set(listOf("equalsHashCode", "toString"))
// Only generates copy
generateMethods.set(listOf("copy"))
// Generates data classes (the default)
generateMethods.set(listOf("dataClass"))
}
}
Enum.values() is no longer recommended when using Kotlin 1.9+ and the generated code now uses entries instead (#5208)Optional<V>.getOrThrow() when V is nullable (#5192)useV3ExceptionHandling only throws when there are no errors populated (#5231)urlEncode algorithm (#5234)keyFields on non-existent fields (#5215)mergeExtensions and toFullSchemaGQLDocument (#5162)Optional<V>.getOrThrow() when V is nullable (#5192)registerOperations {} (#5196)generateMethods options to control which methods are generated on "data" classes (#5212)A lot of additions to the IntelliJ plugin as well as a new GraphQL parser, a new Ktor multiplatform engine and more!
Apollo Kotlin wouldn't be where it is today without the awesome feedback, discussions and contributions from community members. Specifically in this release, we want to give a huge THANK YOU to: @Emplexx, @sonatard, @yt8492, @mayakoneval, @Meschreiber, @pcarrier and @ashare80
The IntelliJ plugin now detects unused fields in your queries and greys them out:
https://github.com/apollographql/apollo-kotlin/assets/372852/6a573a78-4a07-4294-8fa5-92a9ebb02e6c
The IntelliJ plugin can migrate most of your codebase to v4. To try it out, go to:
Tools -> Apollo -> Migrate to Apollo Kotlin 4
Because Kotlin is such a rich language and we can't account for all possible ways to configure your build, you might have to do some manual tweaks after the migration. But the plugin should handle most of the repetitive tasks of migrating.
If you configured introspection, you can now download your schema directly from IntelliJ
<img src="https://github.com/apollographql/apollo-kotlin/assets/372852/3a15f587-b057-4df5-82c0-2e0b0247c203" width=250/>The IntelliJ plugin now has its own dedicated documentation page.
Consult it to find out everything you can do with the plugin as well as installation instructions.
Apollo AST, the GraphQL parser powering Apollo Kotlin is now a manually written recursive descent parser, compared to an automatically generated Antlr parser before. Benchmarks show a x2 to x3 speed improvement and the parser also now supports all platforms Apollo Kotlin supports.
Client Controlled Nullability (CCN) is a GraphQL specification RFC aiming at making it easier to work with GraphQL in type safe languages like Kotlin and Swift.
To use CCN, use the ! and ? CCN modifiers in your queries:
query GetUser {
user {
id
# name is required to display the user
name!
# phoneNumber is optional
phoneNumber?
}
}
The RFC is still in early stages and requires server support. The API and final shape of the RFC might still change. By adding support in Apollo Kotlin, we're hoping to unblock potential users and gather real life feedbacks helping the proposal move forward.
Apollo Kotlin now ships a apollo-engine-ktor that you can use to replace the default HTTP and WebSocket engines of ApolloClient. To use it, add apollo-engine-ktor to your dependencies:
dependencies {
implementation("com.apollographql.apollo3:apollo-engine-ktor")
}
And configure your client to use it:
val apolloClient = ApolloClient.Builder()
.serverUrl("https://example.com/graphql")
.httpEngine(KtorHttpEngine())
.webSocketEngine(KtorWebSocketEngine())
.build()
generateInputBuilders (#5146)For Kotlin codegen, Apollo Kotlin relied on constructors with default arguments. While this works well in most cases, default arguments lack the ability to distinguish between null and absent meaning you have to wrap your values in Optional before passing them to your constructor. If you had a lot of values, it could be cumbersome:
val input = SignupMemberInput(
dob = Utils.changeDateFormat(user.dobMMDDYYYY, "MM/dd/yyyy", "yyyy-MM-dd"),
firstName = Optional.Present(user.firstName),
lastName = user.lastName,
ssLast4 = Optional.Present(user.ssnLastFour),
email = user.email,
cellPhone = Optional.Present(user.phone),
password = user.password,
acceptedTos = true,
formIds = Optional.Present(formIds),
medium = Optional.Present(ConsentMediumEnum.android)
)
To generate Kotlin Builders, set generateInputBuilders to true in your Gradle file:
apollo {
service("api") {
packageName.set("com.example")
generateInputBuilders.set(true)
}
}
With Builders, the same above code can be written in a more fluent way:
val input = SignupMemberInput.builder().apply {
dob(Utils.changeDateFormat(user.dobMMDDYYYY, "MM/dd/yyyy", "yyyy-MM-dd"))
firstName(user.firstName)
lastName(user.lastName)
ssLast4(user.ssnLastFour)
email(user.email)
cellPhone(user.phone)
password(user.password)
acceptedTos(true)
formIds(formIds)
medium(ConsentMediumEnum.ANDROID)
}.build()
Object (#5156)useV3ExceptionHandling(true) to ApolloClient.Builder(). (#5135)A new alpha with updates to the IntelliJ/Android Studio plugin and better JS interop.
You can now navigate from Kotlin both GraphQL or Generated code:
https://github.com/apollographql/apollo-kotlin/assets/3974977/acd4bf34-db35-4442-a7af-b6151701620c
See blog the blog post and installation instructions for more information.
You can now connect the IJ/AS plugin to your GraphOS account. If your backend is configured to report field traces, the plugin will display a warning for expensive fields that may be slow to fetch.
You can configure it in your IJ/AS settings Languages & Frameworks -> GraphQL -> Apollo Kotlin. See also #5048 for a video of the setup.
@jsExportresponseBased codegen can now generate models annotated with @jsExport. This allows to fetch your response using faster JS-only APIs and cast them to the generated models. See the JS interoperability documentation for more information. Many thanks to @baconz for the deep dive 💙
Service.operationManifestFormat (#4981)A maintenance release with bugfixes, mostly around WebSockets and subscriptions as well as a LocalTime adapter and options to work with operation manifests.
Huge THANK YOU to @baconz, @AlexHartford, @Oleur for the love they put in WebSocket contributions as well as @Jephuff for their first contribution 💙 .
Service.operationManifestFormat (#4981)watch() (#4914)This release is the first alpha of the next major version of Apollo Kotlin: 4.0.0.
This version is under development, but we want to give you a preview of what's coming, and get your early feedback. Please see the roadmap for more details about the release plan.
While version 3 changed a lot of APIs compared to version 2, version 4 should be mostly compatible with version 3. Version 4 will even keep the same package name in order to keep the number of changes low.
The error handling has changed but besides that, the version should be mostly compatible. Please consult the migration guide for all the details.
We would love to hear your feedback on this release. Please report any issues, questions, ideas, or comments on the issue tracker.
See this page for installation instructions and more information.
This plugin for Android Studio and IntelliJ helps you work with Apollo Kotlin. It provides the following features:
ApolloResponse.exception for error handlingError handling is an important aspect of a client library and we found it could benefit from some changes.
In particular we are moving away from throwing exceptions:
To that effect, there is now an ApolloResponse.exception : ApolloException property, which will be present when a network error or cache miss have occurred, or when GraphQL errors are present:
val data = response.data
when {
data != null -> {
println("The server returned data: $data")
}
else -> {
// An error happened, check response.exception for more details or just display a generic error
when (response.exception) {
is ApolloGraphQLException -> // do something with exception.errors
is ApolloHttpException -> // do something with exception.statusCode
is ApolloNetworkException -> TODO()
is ApolloParseException -> TODO()
else -> // generic error
}
}
}
To ease the migration to v4, the v3 behavior can be restored by calling ApolloClient.Builder.useV3ExceptionHandling(true).
Feedback about this change is welcome on issue 4711.
apollo-runtime-java for better Java supportAs v3 has a Kotlin and Coroutines first API, using it from Java is sometimes impractical or not idiomatic. That is why in v4 we are introducing a new Java runtime, written in Java, which provides a Java friendly API. It is callback based and doesn't depend on a third-party library like Rx.
To use it in your project, instead of the usual runtime (com.apollographql.apollo3:apollo-runtime), use the following dependency in your build.gradle[.kts] file:
implementation("com.apollographql.apollo3:apollo-runtime-java")
Then you can use the ApolloClient class from Java:
ApolloClient apolloClient = new ApolloClient.Builder()
.serverUrl("https://...")
.build();
apolloClient
.query(MyQuery.builder().build())
.enqueue(new ApolloCallback<MyQuery.Data>() {
@Override public void onResponse(@NotNull ApolloResponse<MyQuery.Data> response) {
System.out.prinitln(response.getData());
}
});
A few examples can be found in the tests.
In multi-module projects, by default, all the types of an upstream module are generated because there is no way to know in advance what types are going to be used by downstream modules. For large projects this can lead to a lot of unused code and an increased build time.
To avoid this, in v3 you could manually specify which types to generate by using alwaysGenerateTypesMatching. In v4 this can now be computed automatically by detecting which types are used by the downstream modules.
To enable this, add the "opposite" link of dependencies with isADependencyOf().
// schema/build.gradle.kts
apollo {
service("service") {
packageName.set("schema")
// Enable generation of metadata for use by downstream modules
generateApolloMetadata.set(true)
// More options...
// Get used types from the downstream module
isADependencyOf(project(":feature1"))
// You can have several downstream modules
isADependencyOf(project(":feature2"))
}
}
// feature1/build.gradle.kts
apollo {
service("service") {
packageName.set("feature1")
// Get the generated schema types (and fragments) from the upstream schema module
dependsOn(project(":schema"))
}
}
This patch release contains 2 bug fixes.
This release adds two new artifacts that contain Jetpack compose extensions amongst other fixes.
Many thanks to @slinstacart and @hbmartin for their contributions to this release!
You can now use the apollo-compose-support artifact:
// build.gradle.kts
dependencies {
implementation("com.apollographql.apollo3:apollo-compose-support")
}
This artifact contains the toState() and watchAsState() extensions:
/**
* A stateful composable that retrieves your data
*/
@OptIn(ApolloExperimental::class)
@Composable
fun LaunchDetails(launchId: String) {
val response by apolloClient.query(LaunchDetailsQuery(launchId)).toState()
val r = response
when {
r == null -> Loading() // no response yet
r.exception != null -> ErrorMessage("Oh no... A network error happened: ${r.exception!!.message}")
r.hasErrors() -> ErrorMessage("Oh no... A GraphQL error happened ${r.errors[0].message}.")
else -> LaunchDetails(r.data!!, navigateToLogin)
}
}
/**
* A stateless composable that displays your data
*/
@Composable
private fun LaunchDetails(
data: LaunchDetailsQuery.Data,
) {
// Your UI code goes here
}
If you are working with paginated data, you can also add apollo-compose-paging-support to your dependencies:
// build.gradle.kts
dependencies {
implementation("com.apollographql.apollo3:apollo-compose-paging-support")
}
This artifact contains a helper function to create androidx.pagin.Pager instances (androix documentation):
@OptIn(ApolloExperimental::class)
@Composable
fun LaunchList(onLaunchClick: (launchId: String) -> Unit) {
val lazyPagingItems = rememberAndCollectPager<LaunchListQuery.Data, LaunchListQuery.Launch>(
config = PagingConfig(pageSize = 10),
appendCall = { response, loadSize ->
if (response?.data?.launches?.hasMore == false) {
// No more pages
null
} else {
// Compute the next call from the current response
apolloClient.query(
LaunchListQuery(
cursor = Optional.present(response?.data?.launches?.cursor),
pageSize = Optional.present(loadSize)
)
)
}
},
getItems = { response ->
// Compute the items to be added to the page from the current response
if (response.hasErrors()) {
Result.failure(ApolloException(response.errors!![0].message))
} else {
Result.success(response.data!!.launches.launches.filterNotNull())
}
},
)
// Use your paging items:
if (lazyPagingItems.loadState.refresh is LoadState.Loading) {
Loading()
} else {
LazyColumn {
items(lazyPagingItems) { launch ->
// Your UI code goes here
}
item {
when (val append = lazyPagingItems.loadState.append) {
is LoadState.Error -> // Add error indicator here
LoadState.Loading -> // Add loading indicator here
}
}
}
}
}
As always, feedback is very welcome. Let us know what you think of the feature by either opening an issue on our GitHub repo , joining the community or stopping by our channel in the KotlinLang Slack(get your invite here).
If you import a new project or run a Gradle sync, your GraphQL models are now automatically generated so that the IDE can find the symbols and your files do not show red underlines. This takes into account Gradle up-to-date checks and it should be pretty fast. If you want to opt-out, you can do so with generateSourcesDuringGradleSync.set(false):
apollo {
// Enable automatic generation of models during Gradle sync (default)
generateSourcesDuringGradleSync.set(true)
// Or disable automatic generation of models to save on your Gradle sync times
generateSourcesDuringGradleSync.set(false)
service("api") {
// Your GraphQL configuration
}
}