迁移到 Apollo Kotlin 3.0
从 2.x 版本开始
Apollo Kotlin 3.0 使用 Kotlin 重新编写了 Apollo Android 的大部分内部代码。除了其他改进外,它还包括:
- Kotlin 首选,协程 API
- 统一的 JVM 和多平台运行时
- 声明式缓存,
@nonnull
客户端 指令,性能改进等等...
尽管库的概念大多数相同,但许多 API 已经更改以更好地在 Kotlin 中运行。
本页描述了最重要的更改,以及如何将现有项目从 Apollo Android 2.x 迁移到 Apollo Kotlin 3.x。
您可以在我们的 GitHub 仓库中打开一个issue、加入社区或者访问 KotlinLang Slack 中的通道(在这里获取邀请)这里)。
快速路径 🚀
Apollo Kotlin 3 提供了一些辅助工具和兼容模式,以简化从 2.x 版本的迁移过程。为了快速达成运行状态,请按照以下步骤进行。一旦你有了可运行的程序,我们强烈建议迁移到本节下面描述的惯用 Apollo Kotlin 3 版本。在未来版本的 Apollo Kotlin 中将移除兼容助手。全部详情。
- 更新你的依赖和导入(
com.apollographql.apollo
→com.apollographql.apollo3
,详见下文部分)。根据需要移除apollo-coroutines-support
和apollo-android-support
。 - Gradle 配置
apollo {// Remove thisgenerateKotlinModels.set(true)// Add thisuseVersion2Compat()}
- Apollo 客户端 配置:
val client = ApolloClient.builder().serverUrl(...)// Replace:.addCustomTypeAdapter(CustomType.YOURTYPE, ...)// With:.addCustomScalarAdapter(YourType.type, ...).build()
全部详情
包名/组 ID/插件 ID
Apollo Kotlin 3.0 使用新的标识符来识别其包名、Gradle 插件 ID 和 Maven 组 ID: com.apollographql.apollo3
。
此改动避免了依赖冲突,正如在 Java 主要版本更新互操作性政策中所倡导的。它还允许在需要时同时运行版本 2 和版本 3。
在大多数情况下,您可以通过执行查找和替换操作来更新项目中的标识符,将 com.apollographql.apollo
替换为 com.apollographql.apollo3
。
组 ID
识别 Apollo Kotlin 3.0 相关元数据的 Maven 组 ID 是 artifacts 是 com.apollographql.apollo3
:
// Replace:implementation("com.apollographql.apollo:apollo-runtime:$version")implementation("com.apollographql.apollo:apollo-api:$version")// With:implementation("com.apollographql.apollo3:apollo-runtime:$version")implementation("com.apollographql.apollo3:apollo-api:$version")
Gradle 插件 ID
Apollo Kotlin 3.0 的 Gradle 插件 ID 是 com.apollographql.apollo3
:
// Replace:plugins {id("com.apollographql.apollo") version "$version"}// With:plugins {id("com.apollographql.apollo3") version "$version"}
包名
所有 Apollo Kotlin 3.0 类都从 com.apollographql.apollo3
包导入:
// Replace:import com.apollographql.apollo.ApolloClient// With:import com.apollographql.apollo3.ApolloClient
Gradle 配置
任务名称
在Apollo Kotlin 3.x中,Gradle插件发生了显著的变化,现在只为所有Android变体生成一次模型。如果您之前使用过类似于 "generateDebugServiceApolloSources" 的任务名称,您现在可以去掉Android变体名称,改为使用 "generateServiceApolloSources"。
generateKotlinModels
如果您正在使用Kotlin Gradle插件,Apollo Kotlin 3.0默认会生成Kotlin模型。您现在可以安全地移除此行为:
apollo {// remove thisgenerateKotlinModels.set(true)}
apollo-coroutines-support
已移除
Apollo Kotlin 3.x以Kotlin为优先,默认暴露挂起函数。因此,不再需要apollo-coroutines-support
。
// Remove:implementation("com.apollographql.apollo:apollo-coroutines-support:$version")
apollo-android-support
已移除
Apollo Android 2.x发布了一个小的工件,以支持在特定的Handler上运行回调并将日志写入logcat。
Apollo Kotlin 3.x使用协程并在其API中公开更多信息,因此不再需要日志钩子。如果您使用日志来获取有关缓存命中/未命中的信息,您现在可以通过捕获CacheMissException
以更类型化的方式获取相同的信息。
// Remove:implementation("com.apollographql.apollo:apollo-android-support:$version")
标量映射
为了明确表明自定义映射仅适用于标量而不是任意类型,customTypeMapping
已被替换为mapScalar
方法。
apollo {// ReplacecustomTypeMapping = ["GeoPoint" : "com.example.GeoPoint","Date" : "com.example.MyDate"]// WithmapScalar("GeoPoint", "com.example.GeoPoint")mapScalar("Date", "com.example.MyDate")}
apollo {// ReplacecustomTypeMapping.set(mapOf("GeoPoint" to "com.example.GeoPoint","Date" to "com.example.MyDate"))// WithmapScalar("GeoPoint", "com.example.GeoPoint")mapScalar("Date", "com.example.MyDate")}
指定模式和 .graphql 文件
Apollo Android 2.x 拥有复杂的逻辑来判断使用哪些文件作为输入。例如,它解析 sourceFolder
相对于多个 Android variants 或 kotlin sourceSets,尝试从模式位置获取 graphql 文件,反之亦然。这种逻辑在大多数情况下都可行,但在更复杂的场景中会使故障排除变得更加复杂。此外,即使在大多数情况下都使用相同的 .graphql 文件,这也将在不同的源集合对于 GraphQL 编译器进行多次运行。
Apollo Kotlin 3.x 简化了这种设置。每个 Service
只有一个编译。对于 Android 项目,GraphQL 类只生成一次,然后添加到所有 variants。
如果您之前使用 graphqlSourceDirectorySet
显式指定 GraphQL 文件的定位,现在您可以使用 srcDir
:
apollo {// ReplacegraphqlSourceDirectorySet.srcDirs += "shared/graphql"// WithsrcDir("shared/graphql")// ReplacegraphqlSourceDirectorySet.include("**/*.graphql")graphqlSourceDirectorySet.exclude("**/schema.graphql")// Withincludes.add("**/*.graphql")excludes.add("**/schema.graphql")}
如果你曾依赖模式位置来自动查找 .graphql 文件,你现在也应添加 srcDir()
来显式设置你的 .graphql 文件位置:
apollo {// ReplaceschemaFile.set(file("src/main/graphql-api/schema.graphqls"))// With// Keep schemaFileschemaFile.set(file("src/main/graphql-api/schema.graphqls"))// explicitly set srcDirsrcDir(file("src/main/graphql-api/"))}
如果您需要为不同变体不同的 GraphQL 操作,您可以使用 apollo.createAllAndroidVariantServices.
包名
Apollo Android 2.x 根据GraphQL 操作 和模式文件的路径,以及 packageName
和 rootPackageName
选项来计算其目标包名。虽然这很灵活,但难以预料最终的包名。
Apollo Kotlin 3.x 默认使用 packageName
选项来使用扁平包名:
apollo {packageName.set("com.example")}
生成的类将是
- com.example.SomeQuery- com.example.fragment.SomeFragment- com.example.type.SomeInputObject- com.example.type.SomeEnum- com.example.type.Types // types is a slimmed down version of the schema
如果您需要在不同的操作文件夹中具有不同的包名,您可以使用以下方式回退到2.x行为:
apollo {packageNamesFromFilePaths("$rootPackageName")# If using version 3.1.0+, you will also need useSchemaPackageNameForFragmentsuseSchemaPackageNameForFragments.set(true)}
为了更精细的控制,您还可以定义自己的 PackageNameGenerator
:
apollo {packageNameGenerator.set(customPackageNameGenerator)}
构建器
在 Apollo Android 2.x 中,您会使用 ApolloClient.builder()
方法来实例化一个新的构建器。在3.x中,请使用 ApolloClient.Builder()
构造函数(注意大写 B
)。
// Replaceval apolloClient = ApolloClient.builder().serverUrl(serverUrl)// ...other Builder methods.build()// Withval apolloClient = ApolloClient.Builder().serverUrl(serverUrl)// ...other Builder methods.build()
操作API
Apollo Android 2.x 有回调API可能会变得冗长,并需要显式处理取消。
Apollo Kotlin 3.x 提供更简洁的协程API,它通过协程作用域自动处理取消。
此外, mutate
已更名为 mutation
,而 subscribe
已更名为 subscription
以保持一致性。
// ReplaceapolloClient.query(query).await()// WithapolloClient.query(query).execute()// ReplaceapolloClient.mutate(query).await()// WithapolloClient.mutation(query).execute()// ReplaceapolloClient.subscribe(query).toFlow()// WithapolloClient.subscription(subscription).toFlow()
自定义标量适配器
Apollo Kotlin 3提供了可选的 apollo-adapters 软件包,它包括常见的 标量 类型的适配器,例如:
KotlinxInstantAdapter
用于kotlinx.datetime.Instant
ISO8601 日期JavaInstantAdapter
用于java.time.Instant
ISO8601 日期KotlinxLocalDateAdapter
用于kotlinx.datetime.LocalDate
ISO8601 日期JavaLocalDateAdapter
用于java.time.LocalDate
ISO8601 日期KotlinxLocalDateTimeAdapter
用于kotlinx.datetime.LocalDateTime
ISO8601 日期JavaLocalDateTimeAdapter
用于java.time.LocalDateTime
ISO8601 日期JavaOffsetDateTimeAdapter
用于java.time.OffsetDateTime
ISO8601 日期DateAdapter
用于java.util.Date
ISO8601 日期BigDecimalAdapter
用于多平台com.apollographql.apollo3.adapter.BigDecimal
类,该类存储大数计算值
要将它们包含在内,请将以下依赖项添加到您的gradle文件中
dependencies {implementation("com.apollographql.apollo3:apollo-adapters:$version")}
如果上述适配器不符合您的需求,或者您需要对其进行自定义,则可以使用自定义 标量适配器 API。
自定义标量适配器 API 为了支持可空值和无值以及流使用情况而进行了大量更改。Apollo Kotlin 3 使可能毫无需要在内存中创建中间副本的情况下读写自定义标量。为此,它使用了内部用于解析模型的相同 Adapter
API:
// Replaceval dateAdapter = object : CustomTypeAdapter<Date> {override fun decode(value: CustomTypeValue<*>): Date {return DATE_FORMAT.parse(value.value.toString())}override fun encode(value: Date): CustomTypeValue<*> {return GraphQLString(DATE_FORMAT.format(value))}}// Withval dateAdapter = object : Adapter<Date> {override fun fromJson(reader: JsonReader, customScalarAdapters: CustomScalarAdapters): Date {return DATE_FORMAT.parse(reader.nextString())}override fun toJson(writer: JsonWriter, customScalarAdapters: CustomScalarAdapters, value: Date) {writer.value(DATE_FORMAT.format(value))}}
JsonReader
和 JsonWriter
API 与您在 Moshi 中找到的 API 类似。JsonReader
和 JsonWriter
是具有状态的 API,您需要按照从 JSON 流接收到的顺序处理 JSON 属性。
// Use AnyAdapter to convert between JsonReader/JsonWriter and a Kotlin Any valueval geoPointAdapter = object : Adapter<GeoPoint> {override fun fromJson(reader: JsonReader, customScalarAdapters: CustomScalarAdapters): GeoPoint {val map = AnyAdapter.fromJson(reader) as Map<String, Double>return GeoPoint(map["latitude"] as Double, map["longitude"] as Double)}override fun toJson(writer: JsonWriter, customScalarAdapters: CustomScalarAdapters, value: GeoPoint) {val map = mapOf("latitude" to value.latitude,"longitude" to value.longitude)AnyAdapter.toJson(writer, map)}}
定义完适配器后,您需要将其注册到您的 ApolloClient
实例。为此,为每个适配器调用一次 ApolloClient.Builder.addCustomScalarAdapter
。
// Replaceval apolloClient = apolloClientBuilder.addCustomTypeAdapter(CustomType.DATE, dateAdapter).build()// Withval apolloClient = apolloClientBuilder.addCustomScalarAdapter(Date.type, dateAdapter).build()
此方法需要一个由 Types
生成的高类型安全类及其相应的适配器。
代码生成
Apollo Kotlin 3.x 提供了 3 种代码生成选项:
- 基于操作: Kotlin 模型映射发送的 GraphQL 操作。
- 基于响应: Kotlin 模型映射接收的 JSON 响应。
- 兼容性: 与 Apollo Kotlin 2.x 兼容。
兼容codegen
会复制一些字段并引入一个额外的.fragments
字段。虽然这是从2.x迁移的简单方法,但一旦您的项目以compat
模式运行,我们建议迁移到operationBased
。
operationBased
codegen更简单,消除了一些字段,并去掉了中间的.fragments
字段。
以下是一个查询示例:
fragment humanDetails on Human {height}query GetHero {hero {name... on Droid {primaryFunction}...humanDetails}}
您可以像这样迁移到operationBased
:
// parent fields are not collected in inline fragments// Replacehero.asDroid?.name// Withhero.name// because parent fields are not collected, inline fragments// are now named "OnFoo" instead of "AsFoo"// Replacehero.asDroid?.primaryFunction// Withhero.onDroid?.primaryFunction// there is no .fragment synthetic field for named fragments// Replacehero.fragments?.humanDetails?.height// Withhero.humanDetails?.height
我们推荐大多数项目使用operationBased
codegen。
要进一步了解,如果您熟悉operationBased
codegen,您可以在设计文档中了解更多关于不同codegen(包括使用responseBased
的权衡)的信息。
标准化缓存
The Apollo Android 2.x runtime has a dependency on the normalized cache APIs, and it's possible to call cache methods even if no cache implementation is in the classpath.
The Apollo Kotlin 3.x runtime is more modular and doesn't know anything about normalized cache by default. To add normalized cache support, add the dependencies to your gradle file:
配置
dependencies {// Replaceimplementation("com.apollographql.apollo:apollo-normalized-cache:$version") // for memory cacheimplementation("com.apollographql.apollo:apollo-normalized-cache-sqlite:$version") // for SQL cache// Withimplementation("com.apollographql.apollo3:apollo-normalized-cache:$version") // for memory cacheimplementation("com.apollographql.apollo3:apollo-normalized-cache-sqlite:$version") // for SQL cache}
// Replaceval cacheFactory = LruNormalizedCacheFactory(EvictionPolicy.builder().maxSizeBytes(10 * 1024 * 1024).build())val apolloClient = ApolloClient.builder().serverUrl("https://...").normalizedCache(cacheFactory).build()// Withval cacheFactory = MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024)val apolloClient = ApolloClient.Builder().serverUrl("https://...").normalizedCache(cacheFactory).build()
配置fetch策略现在是在ApolloCall
实例上进行的:
// Replaceval response = apolloClient.query(query).toBuilder().responseFetcher(ApolloResponseFetchers.CACHE_FIRST).build().await()// Withval response = apolloClient.query(request).fetchPolicy(CacheFirst).execute()
观察者
观察者的默认refetch策略现在是CacheOnly
而不是CACHE_FIRST
。为了保持行为不变,请在您的观察者上设置refetchPolicy
:
val response = apolloClient.query(query).watcher().toFlow()// Withval response = apolloClient.query(query).refetchPolicy(CacheFirst).watch()
CacheKeyResolver
CacheKeyResolver API已被划分为两个不同的API:
CacheKeyGenerator.cacheKeyForObject
- 接受JSON数据作为输入,为一个对象返回一个唯一ID。
- 在处理网络请求后 使用。
- 在写入缓存时进行正常化处理时 使用。
CacheKeyResolver.cacheKeyForField
- 接受一个GraphQL 字段和操作变量作为输入,并为该字段生成一个ID。
- 在处理网络请求之前使用。
- 读取缓存时使用。
以前,这两种方法都包含在CacheResolver
类中,尽管底层代码路径非常不同。通过分离它们,使它们更加明确,并有可能仅实现其中之一。
从高层次来看,
fromFieldRecordSet
已更名为CacheKeyGenerator.cacheKeyForObject
。fromFieldArguments
已更名为CacheKeyResolver.cacheKeyForField
。- 现在,
CacheKey
返回值现在是可空的,CacheKey.NONE
已用null
替换。
// Replaceval resolver: CacheKeyResolver = object : CacheKeyResolver() {override fun fromFieldRecordSet(field: ResponseField, recordSet: Map<String, Any>): CacheKey {return CacheKey.from(recordSet["id"] as String)}override fun fromFieldArguments(field: ResponseField, variables: Operation.Variables): CacheKey {return CacheKey.from(field.resolveArgument("id", variables) as String)}}val apolloClient = ApolloClient.builder().serverUrl("https://...").normalizedCache(cacheFactory, resolver).build()// Withval cacheKeyGenerator = object : CacheKeyGenerator {override fun cacheKeyForObject(obj: Map<String, Any?>, context: CacheKeyGeneratorContext): CacheKey? {return obj["id"]?.toString()?.let { CacheKey(it) } ?: TypePolicyCacheKeyGenerator.cacheKeyForObject(obj, context)}}val cacheKeyResolver = object : CacheKeyResolver() {override fun cacheKeyForField(field: CompiledField, variables: Executable.Variables): CacheKey? {return (field.resolveArgument("id", variables) as String?)?.let { CacheKey(it) }}}val apolloClient = ApolloClient("https://").normalizedCache(normalizedCacheFactory = cacheFactory,cacheKeyGenerator = cacheKeyGenerator,cacheResolver = cacheKeyResolver)
缓存缺失现在总是抛出异常
在Apollo Android 2中,具有CacheOnly
策略的缓存缺失返回一个包含response.data = null
的ApolloResponse
。这与将缓存缺失视为错误的CacheFirst
策略不一致。
在Apollo Android 3中,调用ApolloCall.execute()
保证总是返回一个有效(可能是部分)的ApolloResponse
或抛出异常。
如果您有任何CacheOnly
查询,请确保捕获其结果:
try {apolloClient.query(query).fetchPolicy(CacheOnly)} catch (e: ApolloException) {// handle error}
HTTP缓存
要添加http缓存支持,请将依赖项添加到您的gradle文件中
dependencies {// Addimplementation("com.apollographql.apollo3:apollo-http-cache:$version") // Gives access to `httpCache` and `httpFetchPolicy`}
同样,HTTP缓存可以通过扩展函数进行配置
// Replaceval cacheStore = DiskLruHttpCacheStore()val apolloClient = ApolloClient.builder().serverUrl("/").httpCache(ApolloHttpCache(cacheStore)).build()// Withval apolloClient = ApolloClient.Builder().serverUrl("https://...").httpCache(File(cacheDir, "apolloCache"), 1024 * 1024).build()
现在在ApolloCall
实例上配置HTTP抓取策略:
// Replaceval response = apolloClient.query(query).toBuilder().httpCachePolicy(HttpCachePolicy.CACHE_FIRST).build().await()// Withval response = apolloClient.query(request).httpFetchPolicy(CacheFirst).execute()
为了与标准化缓存保持一致,默认的httpFetchPolicy
现在是HttpFetchPolicy.CacheFirst
。为了保持与2.0相同的默认行为,请使用HttpFetchPolicy.NetworkOnly
。
可选值
Optional
类
Apollo Kotlin 区分了null
值和不存在值。
Apollo Android 2.x 使用Input
表示输入类型的可选(可能为可空的)值。
Apollo Kotlin 3.x使用Optional
以实现对可能的输入类型以外的使用(例如,字段可以使用@optional标记为可选,详情请见https://github.com/apollographql/apollo-android/blob/5c1ff82ccaded93ae7126cedc6d7835e63fed75a/apollo-compiler/src/main/resources/apollo.graphqls#L6)。
Optional
是一个封闭类,因此when
语句不需要else
分支。
// ReplaceInput.fromNullable(value)// WithOptional.Present(value)// ReplaceInput.absent()// WithOptional.Absent// ReplaceInput.optional(value)// WithOptional.presentIfNotNull(value)
非可选变量的生成
默认情况下,GraphQL规范将可为空的变量视为可选,因此可以在运行时省略它们。然而,在实践中,这很少使用,并且会使操作声明更冗长。
因此,Apollo Kotlin 3.x提供了移除Optional
包装器的机制,这使得构建带有可为空变量的查询更加直接。
当启用时,此新行为仅适用于变量。 字段仍使用Optional
,因为省略具体的输入字段是常见的情况。
全局在Gradle配置中省略可选变量:
apollo {// ...generateOptionalOperationVariables.set(false)}
如果您仍然需要在某些地方省略变量,您可以选择使用Optional
包装器与@optional
指令来启用它:
query GetHero($id: String @optional) {hero(id: $id)}
更多详细信息请点击此处。
枚举
Apollo Android 2.x总是将枚举和枚举值名称转换为大写。
Apollo Kotlin 3.x使用枚举以及枚举值名称的方案大小写。这允许定义具有不同大小写的多个枚举值:
# This now generates valid Kotlin codeenum Direction {left @deprecated("use LEFT instead")LEFT,RIGHT}
有关更多详细信息,请参阅#3035。
IdlingResource
在Apollo Android 2.x中,您可以将ApolloClient
传递给ApolloIdlingResource.create()
,然后ApolloClient
将被修改以注册空闲回调。
在 Apollo Kotlin 3.x 中,一旦实例化 ApolloClient
,它就是不可变的,因此一旦实例化之后就不能再注册回调或拦截器。相反,您可以首先创建您的 ApolloIdlingResource
,然后将它传递给您的 ApolloClient.Builder
,如下所示:
// Replaceval idlingResource = ApolloIdlingResource.create("ApolloIdlingResource", apolloClient)IdlingRegistry.getInstance().register(idlingResource)// Withval idlingResource = ApolloIdlingResource("ApolloIdlingResource")IdlingRegistry.getInstance().register(idlingResource)val apolloClient = ApolloClient.Builder().serverUrl("https://example.com/graphql").idlingResource(idlingResource).build()
BigDecimal
默认情况下,Apollo Android 2.x 在内部将所有数字映射到一个自定义的 BigDecimal
值。
出于性能考虑,Apollo Kotlin 3.x 在可能的情况下使用原始类型,并将 BigDecimal
移动到 apollo-adapters
库中。
如果您在您的模式中使用自定义 scalars
来表示大数,那么现在您应该明确地将它们添加到您的 Gradle 配置中:
dependencies {implementation("com.apollographql.apollo3:apollo-adapters:x.y.z")}apollo {mapScalar("Decimal","com.apollographql.apollo3.adapter.BigDecimal","com.apollographql.apollo3.adapter.BigDecimalAdapter")}
如果您没有使用大数自定义 scalars
,但是您正在定义自己的适配器,您可能仍然受到影响。在这种情况下,您可能收到的将是 Int
或 Double
而不是 BigDecimal
:
val customTypeAdapter = object: CustomTypeAdapter<Address> {override fun decode(value: CustomTypeValue<*>): Address {check (value is CustomTypeValue.GraphQLJsonObject)val street = value.value["street"] as String// BigDecimal is not exposed anymore// Replace// val number = value.value["number"] as BigDecimal// Withval number = value.value["number"] as Intreturn Address(street, number)}}
默认情况下,如果数字不适合在 Int
中,它将被映射到 Int
或 Double
。如果数字也不适合在 Double
中,它将回退到一个包含数字的字符串表示的 JsonNumber
。
ApolloLogger
Apollo Android 2.x 有一个 ApolloLogger
接口。其主要用例之一是记录缓存未命中。
Apollo Android 3.x 删除了这个接口,并使用 API 暴露了这个信息。API 提供了更结构化和可维护的方式来暴露数据。
对于自定义日志记录,您可以现在使用一个 ApolloInterceptor
。
对于缓存未命中,您可以使用便利方法 ApolloClient.Builder.logCacheMisses()
:
val apolloClient = ApolloClient.Builder().serverUrl(mockServer.url()).logCacheMisses() // Put this before setting up your normalized cache.normalizedCache(MemoryCacheFactory()).build()
Subscriptions
Apollo Android 2.x 有一个 SubscriptionManager
类。这个类公开了很多关于 Websocket 状态管理的方法和数据。虽然非常灵活,但难以维护和演进。
Apollo Android 3.x instead 使用 WebsocketNetworkTransport
来暴露一个简化的 API:
protocolFactory
允许使用graphql-ws
或 AppSync(或您的自定义之一)作为较低级别的协议,而不是默认协议。reopenWhen
允许在出现网络错误或其他错误的情况下自动重新订阅。
如果您之前使用过 apolloClient.subscriptionManager.reconnect()
来强制 Websocket 重连(例如发送新的认证参数),现在您可以调用 apolloClient.subscriptionNetworkTransport.closeConnection(<your exception>)
:这会表现得好像发生了网络错误,并且您可以通过 reopenWhen
来对这种错误做出响应。
如果您之前正在使用 subscriptionConnectionParams
对您的 订阅 进行身份验证,现在您可以使用 wsProtocol
与一个包含在 SubscriptionWsProtocol.Factory
中的 connectionPayload
。更多信息请在 WebSockets 身份验证 中查看。
如果您觉得 SubscriptionManager
中缺少某些 API,请 联系我们,以便我们讨论最佳添加方法。
下载模式
由于无法可靠地确定 Gradle 当前工作目录,downloadApolloSchema
任务现在使用相对于根项目目录的路径:
# schema is now interpreted relative to the root project directory and# not the current working directory anymore. This example assumes there# is a 'app' module that applies the apollo plugin./gradlew downloadApolloSchema \--endpoint="https://your.domain/graphql/endpoint" \--schema="app/src/main/graphql/com/example/schema.graphqls"
如果您在 Gradle 脚本中配置了 introspection {}
或 registry {}
块,现在应该使用 downloadServiceApolloSchemaFromIntrospection
或 downloadServiceApolloSchemaFromRegistry
OkHttp
由于 3.x 是多平台优先的,运行时抽象了 OkHttp,位于 HttpEngine API 之下。如果您依赖于 OkHttpExecutionContext
,您现在可以使用 HttpInfo
来访问 HTTP 响应代码和头信息:
// Replaceresponse.executionContext[OkHttpExecutionContext].response.code// Withresponse.executionContext[HttpInfo]?.statusCode
在未使用运行时的情况下使用模型
API 已更新以允许流式使用情况。要组合请求体
// Replaceval request = query.composeRequestBody()// Withval request = buildJsonString {query.composeJsonRequest(this, CustomScalarAdapters.Empty)}
要解析响应体
// Replaceval response = query.parse(bufferedSource);// Withval response = query.parseJsonResponse(bufferedSource);
refetchQueries()
Apollo Android 2.x 暴露了 ApolloCall.Builder.refetchQueries(List<Query>)
。这用于在影响其他查询的 变异 后从网络获取新值。这提供了对错误处理、缓存或并发性的有限控制。
Apollo Kotlin 3.x 暴露了一个协程 API,便于在不使用库的情况下实现类似的功能。协程使得调用链式、错误重试以及改变调度程序变得容易。对于简单版本,你可以这样做:
suspend fun <MutationData: Mutation.Data> mutation(mutation: Mutation<MutationData>, vararg refetchQueries: Query<*>) {apolloClient.mutation(mutation).execute()refetchQueries.forEach {apolloClient.query(it).execute()}}
如果您想将更新绑定到 ApolloClient 的作用域中,您可以使用
suspend fun <MutationData: Mutation.Data> mutation(mutation: Mutation<MutationData>, vararg refetchQueries: Query<*>) {apolloClient.mutation(mutation).execute()apolloClient.executionContext[ConcurrencyInfo]!!.coroutineScope.launch {refetchQueries.forEach {apolloClient.query(it).execute()}}}
尚未计划在库中添加 refetchQueries()
。