十月八日至十日在纽约市与我们相聚,了解关于 GraphQL 联邦和 API 平台工程的最新的技巧、趋势和新闻。在纽约市的 GraphQL 峰会 2024 上与我们相聚
文档
免费开始
您正在查看此软件的早期版本的文档。 切换到最新稳定版本。

10. 身份验证您的操作


在本节中,您将预订航班 🚀!预订航班需要向服务器进行身份验证,以确保正确的发送到太空的人!为此,由于 Apollo Kotlin 用来 OkHttp来处理 HTTP 请求,您将使用 OkHttp 拦截器向您的 GraphQL 请求添加头部。

添加拦截器

Apollo.kt中添加 AuthorizationInterceptor类:

app/src/main/kotlin/com/example/rocketreserver/Apollo.kt
private class AuthorizationInterceptor() : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request().newBuilder()
.apply {
TokenRepository.getToken()?.let { token ->
addHeader("Authorization", token)
}
}
.build()
return chain.proceed(request)
}
}

此拦截器若 token 不为 null 则将 "Authorization: $token" HTTP 头部添加到请求中。

使用拦截器

创建一个自定义的 OkHttpClient,使用此拦截器并将其传递给 ApolloClient

app/src/main/kotlin/com/example/rocketreserver/Apollo.kt
val apolloClient = ApolloClient.Builder()
.serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
.okHttpClient(
OkHttpClient.Builder()
.addInterceptor(AuthorizationInterceptor())
.build()
)
.build()

添加 BookTrip 和 CancelTrip 模式

schema.graphqls 文件旁边添加一个 BookTrip.graphql 文件:

app/src/main/graphql/BookTrip.graphql
mutation BookTrip($id:ID!) {
bookTrips(launchIds: [$id]) {
success
message
}
}

注意 bookTrips 字段接收一个列表作为 ,但 自己只接收单个

另外,添加一个 CancelTrip.graphql 文件。这个 mutation 没有使用列表:

app/src/main/graphql/CancelTrip.graphql
mutation CancelTrip($id:ID!) {
cancelTrip(launchId: $id) {
success
message
}
}

将mutations与UI连接

回到 LaunchDetails.kt,并将 TODO 替换为执行适当的 mutation,根据 是否已预订:

app/src/main/java/com/example/rocketreserver/LaunchDetails.kt
private suspend fun onBookButtonClick(launchId: String, isBooked: Boolean, navigateToLogin: () -> Unit): Boolean {
if (TokenRepository.getToken() == null) {
navigateToLogin()
return false
}
val mutation = if (isBooked) {
CancelTripMutation(id = launchId)
} else {
BookTripMutation(id = launchId)
}
val response = try {
apolloClient.mutation(mutation).execute()
} catch (e: ApolloException) {
Log.w("LaunchDetails", "Failed to book/cancel trip", e)
return false
}
if (response.hasErrors()) {
Log.w("LaunchDetails", "Failed to book/cancel trip: ${response.errors?.get(0)?.message}")
return false
}
return true
}

现在回到 LaunchDetails 函数,声明一个协程作用域以便调用 onBookButtonClick。让我们记住 isBooked 并相应地更改按钮的文本:

app/src/main/java/com/example/rocketreserver/LaunchDetails.kt
// Book button
val scope = rememberCoroutineScope()
var isBooked by remember { mutableStateOf(data.launch?.isBooked == true) }
Button(
modifier = Modifier
.padding(top = 32.dp)
.fillMaxWidth(),
onClick = {
scope.launch {
val ok = onBookButtonClick(
launchId = data.launch?.id ?: "",
isBooked = isBooked,
navigateToLogin = navigateToLogin
)
if (ok) {
isBooked = !isBooked
}
}
}
) {
Text(text = if (!isBooked) "Book now" else "Cancel booking")
}

还要添加一个加载指示器,并在 mutation 执行时防止按钮被点击:

app/src/main/java/com/example/rocketreserver/LaunchDetails.kt
// Book button
var loading by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
var isBooked by remember { mutableStateOf(data.launch?.isBooked == true) }
Button(
modifier = Modifier
.padding(top = 32.dp)
.fillMaxWidth(),
enabled = !loading,
onClick = {
loading = true
scope.launch {
val ok = onBookButtonClick(
launchId = data.launch?.id ?: "",
isBooked = isBooked,
navigateToLogin = navigateToLogin
)
if (ok) {
isBooked = !isBooked
}
loading = false
}
}
) {
if (loading) {
SmallLoading()
} else {
Text(text = if (!isBooked) "Book now" else "Cancel booking")
}
}

预订您的旅行!

编译并运行您的应用程序。您现在可以预订和取消您的旅行!按钮将根据旅行是否已预订而改变。

在下一节中,您将 编写您的第一个订阅并在有人预订航班时实时通知。

上一页
9. 编写您的第一个mutation
下一页
11. 编写您的第一个订阅
评价文章评价

©2024Apollo Graph Inc.,以Apollo GraphQL名义运营。

隐私政策

公司