Apollo Kotlin中的订阅
订阅是长期存在的GraphQL读取操作,可以在一段时间内更新其响应,使客户端能够随着数据变得可用而接收新数据。
GraphQL规范没有指定用于订阅操作的特定协议。Apollo Kotlin支持以下协议:
- WebSocket,使用以下子协议之一:
- subscriptions-transport-ws (⚠️ 未再维护!)
- graphql-ws
- appsync(也使用了
graphql-ws
作为Sec-WebSocket-Protocol)
- HTTP,使用分块多部分响应
您必须使用GraphQL端点支持的任何传输方式。
您在应用程序中定义一个 subscription就像定义一个查询一样,只不过您使用subscription
关键字。以下是一个获取数值每次递增的最新值的 subscription示例:
subscription NumberIncremented {numberIncremented}
与查询和突变不同,订阅操作只可以包含一个(一个)订阅类型中的字段。字段。要订阅多个字段,您需要创建多个订阅操作。
ⓘ 注意
从4.0.0版本开始,Apollo Kotlin提供了一个新的实验性WebSocket实现,提供了更好的默认设置、更好的重试和错误处理API。它旨在未来替换当前的实现。
如果您想尝试一下,请查阅实验性WebSocket页面。
配置WebSocket订阅
默认情况下,Apollo Kotlin通过subscriptions-transport-ws
协议,通过SubscriptionWsProtocol
类对订阅进行操作。此协议不再积极维护。它保持默认状态,用于向后兼容。
Apollo Kotlin的研究版本将默认设置为更新的graphql-ws
协议和GraphQLWsProtocol
类。如果您的服务器已经使用graphql-ws
,请确保将您的WsProtocol
设置为GraphQLWsProtocol。
要使用WebSocket进行订阅,请使用WebSocketNetworkTransport
:
val apolloClient = ApolloClient.Builder().subscriptionNetworkTransport(WebSocketNetworkTransport.Builder().serverUrl("https://example.com/graphql").build()).build()
ⓘ 注意
Apollo Kotlin支持https://
(或http://
)和wss://
(或ws://
)协议。内部,wss://
被重命名为https://
,您使用哪个都无关紧要。
自定义您的WebSocket协议
默认情况下,Apollo Kotlin使用subscriptions-transport-ws以实现后向兼容性,但它支持以下所有WebSocket子协议:
- subscriptions-transport-ws (⚠️未积极维护!)
- graphql-ws
- appsync(也使用
graphql-ws
作为Sec-WebSocket-Protocol)
要自定义协议,请使用WsProtocol
接口。Apollo Kotlin内置了对上述子协议的支持:
子协议 | 类 |
---|---|
subscriptions-transport-ws | SubscriptionWsProtocol (默认) |
graphql-ws | GraphQLWsProtocol |
appsync | AppSyncWsProtocol |
例如,您可以这样配置graphql-ws
传输:
val apolloClient = ApolloClient.Builder().subscriptionNetworkTransport(WebSocketNetworkTransport.Builder().protocol(GraphQLWsProtocol.Factory()).serverUrl("https://example.com/graphql").build()).build()
AWS (Amplitude) AppSync
配置AppSync相对简单,但由于AppSync的授权和域要求,存在一些细微之处。特别是,自定义域上的AppSync
private const val REALTIME = "realtime"private fun wsUrl(url: String, auth: Map<String, String>): String {val realtimeUrl = when {url.contains(REALTIME) -> urlurl.contains("amazonaws.com") -> {val awsUrlParts = url.split("appsync-api")require(awsUrlParts.size == 2) { "Invalid AWS url: $url" }"${awsUrlParts[0]}appsync-realtime-api${awsUrlParts[1]}"}url.endsWith("/") -> "$url$REALTIME"else -> "$url/$REALTIME"}return AppSyncWsProtocol.buildUrl(baseUrl = realtimeUrl,authorization = auth,)}// assumes host and key variables have already been setprivate fun wsAuth(): Map<String, String> = mapOf("host" to host, "x-api-key" to key)val apolloClient = ApolloClient.Builder().subscriptionNetworkTransport(WebSocketNetworkTransport.Builder()// if you know that your URL is correct for realtime then below could be// .serverUrl(AppSyncWsProtocol.buildUrl(url, wsAuth()).serverUrl(wsUrl(url, wsAuth())).protocol(AppSyncWsProtocol.Factory(connectionPayload = { wsAuth() })).build(),).build()
身份验证
请参阅本部分了解WebSocket的身份验证。
配置HTTP订阅
要使用HTTP进行订阅,请使用以下HttpNetworkTransport
:
val apolloClient = ApolloClient.Builder().subscriptionNetworkTransport(HttpNetworkTransport.Builder().serverUrl("https://example.com/graphql").build()).build()
这仅是所需的配置。 HttpNetworkTransport
将使用 分块的多部分响应 用于 订阅 操作以及标准 POST 或 GET 请求用于查询和 变体。
监听订阅
配置好 NetworkTransport
后,使用 ApolloClient.subscription
打开连接并监听更改:
apolloClient.subscription(TripsBookedSubscription()).toFlow().collect {println("trips booked: ${it.data?.tripsBooked}")}
由于 订阅 是长期操作,你应该调用 toFlow()
获取 Flow<Response>
而不是单个 Response
。
终止订阅
终止通过协程作用域处理。取消协程以终止 订阅。
默认情况下,所有活跃的 订阅 之间共享一个 WebSocket。当没有活跃的订阅时,WebSocket 将在可配置的超时后关闭。
错误处理
与查询类似, 订阅 支持带有 GraphQL 错误的局部响应,这些错误在 Flow
中发出。
网络错误会终止 Flow
,你需要重试以获取新更新。根据情况,重试可能会打开一个新的 WebSocket 或重新启动 订阅。
有关 WebSocket 错误处理的更多信息,请参阅此部分:此部分。