迁移到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 仓库中提交问题, 加入社区 或 访问 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 Client配置:
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 是 工件,它为 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" 这样的任务名称,现在您可以使用 "generateServiceApolloSources" 而不是 Android 变体名称。
生成Kotlin模型
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 变体 或 kotlin 源集,尝试从模式位置获取 graphql 文件,反之亦然。这种逻辑在大多数情况下都可行,但在更复杂的情况下,会遇到更复杂的调试问题。此外,它会在不同的源集中多次运行 GraphQL 编译器,即使在大多数情况下,使用的 .graphql 文件是相同的。
Apollo Kotlin 3.x 简化了这种设置。每个 Service
只进行一次编译。对于 Android 项目, GraphQL 类只生成一次,然后添加到所有 变体 中。
如果您之前使用了 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 创建每个 Android 变体的多个服务。
包名
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,它们要求您按顺序处理来自 JSON 流的 JSON 属性。如果您愿意,还可以将 JSON 缓冲到未类型化的 Any?
值中,该值表示 json,并使用 AnyAdapter
对其进行解码/编码:
// 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 种代码生成选项:
- operationBased: Kotlin 模型映射发送的 GraphQL 操作。
- responseBased: Kotlin 模型映射接收的 Json 响应。
- compat: 与 Apollo Kotlin 2.x 的兼容性
在兼容代码生成中,一些字段被重复,并引入了一个额外的.fragments字段。虽然这是一个方便从2.x迁移的方法,但我们建议您的项目以兼容模式运行后,迁移到基于操作。
基于操作的代码生成更简单,减少了某些字段,并删除了中间的:.fragments字段。
给定以下查询:
fragment humanDetails on Human {height}query GetHero {hero {name... on Droid {primaryFunction}...humanDetails}}
您可以像这样迁移到 基于操作:
// 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
我们推荐对大多数项目使用 基于操作代码生成。
如果您熟悉 基于操作代码生成,可以在设计文档中了解有关不同代码生成器(包括使用
基于响应的权衡)的更多信息。
规范化缓存
Apollo Android 2.x运行时依赖于规范化缓存API,即使在类路径中没有实现缓存,也可以调用缓存方法。
Apollo Kotlin 3.x运行时更加模块化,默认情况下不知道任何东西关于规范化缓存。要添加规范化缓存支持,将依赖项添加到您的gradle文件中:
配置
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 policy是在ApolloCall
实例上进行的:
// Replaceval response = apolloClient.query(query).toBuilder().responseFetcher(ApolloResponseFetchers.CACHE_FIRST).build().await()// Withval response = apolloClient.query(request).fetchPolicy(CacheFirst).execute()
观察者
观察者现在默认使用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的返回值现在是nullable的,并且将
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
。
可选值
The Optional
class
Apollo Kotlin区分空值和不存在值。
Apollo Android 2.x使用Input
表示输入类型中的可选(可能为null)值。
Apollo Kotlin 3.x 使用 Optional
来代替,这样以后它可以在除了输入类型以外的位置使用,例如,可以使用 指令 @optional 将字段设置为可选。@optional
指令).
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 总是将枚举和枚举值名称转换为 uppercase。
Apollo Kotlin 3.x 使用 schema case 上下文为枚举和枚举值名称,这允许定义多个具有不同 case 的枚举值:
# 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
模块。
如果您在您的模式中使用了自定义big decimal标量,现在应该明确地将它们添加到您的Gradle配置中:
dependencies {implementation("com.apollographql.apollo3:apollo-adapters:x.y.z")}apollo {mapScalar("Decimal","com.apollographql.apollo3.adapter.BigDecimal","com.apollographql.apollo3.adapter.BigDecimalAdapter")}
如果您没有使用big decimal自定义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使用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 是多平台优先的,因此运行时在 HttpEngine API 的背后抽象化了 OkHttp。如果您依赖于 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()
。