11. 编写您的第一个订阅
在本节中,您将使用订阅功能,以便在有人预订航班🚀时接收通知!订阅 允许在服务器上的事件发生时实时接收通知。 后端 基于订阅 基于 WebSocket。
编写您的订阅
打开您的 沙盒,点击左侧的 Schema 选项卡。除了 查询
和突变
,您将看到一个第三种类型的根字段:订阅
。单击订阅以查看tripsBooked
字段:
此字段不接受任何参数并返回一个名为tripsBooked
的单个标量。由于您可以一次性预订多个行程,因此tripsBooked
是一个Int
。它将包含一次性预订的行程数或行程被取消时的-1。
单击tripsBooked
左边的播放按钮以在探索器中打开该字段。打开一个新标签页,然后检查tripsBooked
旁边的加号按钮以添加该字段:
再次重命名您的订阅,以便更容易找到:
单击提交操作按钮,您的订阅将开始侦听事件。您可以告诉它正在运行,因为将在左下角弹出一个面板,其中将显示订阅数据:
测试您的订阅
在探索器中打开一个新标签页。在这个新标签页中,添加一段代码来预订行程,类似于第9步,但带有硬编码的ID:
mutation BookTrip {bookTrips(launchIds: ["93"]){message}}
请确保包含身份验证头。在添加操作的Sandbox Explorer面板的底部,有一个Headers
部分:
点击“提交 操作按钮。如果一切顺利,你已经预订了旅行!在右侧面板的顶部,你会看到你 BookTrip
的成功JSON,下面是TripsBooked
订阅的更新JSON:
继续预订和/或取消旅程,你将实时看到发生在订阅面板中的事件。一段时间后,服务器可能会关闭连接,你必须重新启动你的订阅以继续接收事件。
将订阅添加到项目中
现在你的订阅正在运行,将其添加到你的项目中。创建一个名为TripsBooked.graphql
的文件,放在schema.graphqls
和你的其他GraphQL文件旁边,并将订阅的内容粘贴进去。这个过程与你在查询和mutations时所做的类似:
subscription TripsBooked {tripsBooked}
配置ApolloClient以使用订阅
本教程使用subscriptions-transport-ws
协议进行订阅。关于全新graphql-ws
或 Appsync等更多选项,请查看GraphQL通过WebSocket协议。
在 Apollo.kt
中,为你的 ApolloClient
配置一个 webSocketServerUrl
:
val apolloClient = ApolloClient.Builder().serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql").webSocketServerUrl("wss://apollo-fullstack-tutorial.herokuapp.com/graphql").okHttpClient(...).build()
wss://
是WebSocket的协议。
在预定或取消旅行时显示Snackbar
在 MainActivity
中,注册你的订阅并保留返回的协程Flow的引用。
使用collectAsState
以获取Flow的最新值作为状态。当Flow发出值时,该值将存储在tripBookedResponse
中,并由依赖于它的LaunchedEffect
触发UI的重构。
RocketReserverTheme {val tripBookedFlow = remember { apolloClient.subscription(TripsBookedSubscription()).toFlow() }val tripBookedResponse: ApolloResponse<TripsBookedSubscription.Data>? by tripBookedFlow.collectAsState(initial = null)LaunchedEffect(tripBookedResponse) {if (tripBookedResponse == null) return@LaunchedEffectval message = when (tripBookedResponse!!.data?.tripsBooked) {null -> "Subscription error"-1 -> "Trip cancelled"else -> "Trip booked! 🚀"}// TODO use the message}
现在让我们在Material SnackBar中显示信息。
为此,您需要创建一个SnackbarHostState
并在其上调用showSnackbar
。不要忘记将其传递到下面的Scaffold
中:
val snackbarHostState = remember { SnackbarHostState() }val tripBookedFlow = (...)(...)val message = (...)snackbarHostState.showSnackbar(message = message,duration = SnackbarDuration.Short)}Scaffold(topBar = { TopAppBar({ Text(stringResource(R.string.app_name)) }) },snackbarHost = { SnackbarHost(snackbarHostState) },) { paddingValues ->
处理错误
就像查询和mutations一样,如果连接丢失或发生其他协议错误,订阅将引发错误。要处理这些情况,您可以配置客户端使用webSocketReopenWhen
函数重试订阅。返回true
以重试,返回false
以停止。为了避免过于频繁的重试,您可以使用attempt
参数来延迟重试:
val apolloClient = ApolloClient.Builder()(...).webSocketReopenWhen { throwable, attempt ->Log.d("Apollo", "WebSocket got disconnected, reopening after a delay", throwable)delay(attempt * 1000)true}
测试您的代码
构建并运行您的应用,然后回到Sandbox Explorer,选择您设置BookTrip
突变选项卡的标签页。当您的应用打开时预订新行程,你应该看到一个Snackbar 🚀
本教程到此结束,恭喜!🎉
更多资源
使用本文档的其余部分了解更多高级主题,如缓存或Gradle配置。