Apollo Kotlin中的查询
以可预测、类型安全的方式获取数据是Apollo Kotlin的核心特性之一。Apollo Kotlin。在本指南中,您将了解如何查询一个GraphQL端点并将结果用于您的应用程序。
先决条件
本页假设您对构建GraphQL查询有一定的了解。为了巩固,我们建议您阅读此指南和练习在Apollo沙盒中运行查询。
因为 Apollo Kotlin 使用标准的 GraphQL 语法,您在沙盒中可以运行的任何查询也可以放入 .graphql文件中。
此页面还假设您已为您的 Android/Kotlin 应用设置了 Apollo Kotlin。有关设置的帮助,请参阅 入门指南。
定义
在 Apollo Kotlin 中,每个您执行的 查询 都表示为实现了 Query 接口 的类实例。为了生成这些类,我们首先需要定义我们想要执行的 GraphQL 操作。
假设我们定义了一个名为 GraphQL 查询的名为 HeroQuery,如下所示:
query HeroQuery($id: String!) {hero(id: $id) {idnameappearsIn}}
如果我们将此 查询 放在它自己的 .graphql 文件中, Apollo Kotlin 将生成相应的 HeroQuery 类,我们可以使用它来 执行查询。
为了生成类, Apollo Kotlin 需要您的服务器模式,以及包含您的定义 .graphql 操作的所有 文件。它使用这些文件来生成可以用于执行查询和访问类型化结果的代码。
在您的项目(或您作为输入传递给apollo-codegen的自定脚本的子集)中的所有.graphql文件都将合并并作为一个 GraphQL文档处理。这意味着,在一个.graphql文件中定义的片段在所有所有 .graphql文件中都是可用的。但是,这也意味着操作和片段的名称必须是唯一的(如果不唯一,将会发生验证错误)。
执行
为了执行我们刚刚定义的查询,我们将一个HeroQuery实例传入到ApolloClient的query方法中,如下所示:
val apolloClient = ApolloClient.Builder().serverUrl("https://your.domain/graphql").build()val response = apolloClient.query(HeroQuery(id = "12")).execute()
默认情况下,Apollo Kotlin将I/O工作卸载到后台线程,这意味着在主线程上启动GraphQL操作是安全的。结果也将被调度到调用线程,并且您可以直接使用响应来更新您的数据。
- 在JVM上,默认使用
Dispatchers.IO进行I/O工作。您可以使用ApolloClient.Builder.dispatcher更改此调度程序。 - 在Kotlin/native(iOS、macOS、...)上,请求将缓存和网络I/O卸载到恢复到主调度队列的后台线程。因此,
ApolloClientAPI 假设它们是在主线程中调用的。无法自定义调度程序,但缓存和网络I/O始终在后台线程中执行。
结果
一个查询的结果以匹配查询字段结构的不可变类层次结构返回。这些类仅包含在查询中包含的字段(省略其他schema字段)。
换句话说,Apollo Kotlin
根据您编写的查询生成类,而不是根据您查询的模式。
例如,给定以下模式:
enum Episode { NEWHOPE, EMPIRE, JEDI }interface Character {id: String!name: String!friends: [Character]appearsIn: [Episode]!}
以及以下查询:
query HeroAndFriendsNames {hero {namefriends {idname}}}
Apollo Kotlin生成一个看起来这样的类型安全的模型(省略细节以关注类结构):
class HeroAndFriendsNamesQuery {data class Data(val hero: Hero)data class Hero(val name: String, friends: List<Friend>)data class Friend(val id: String, val name: String)}
因为 HeroAndFriendsNames 查询不获取 appearsIn,所以这个属性不是返回结果类型的一部分,无法在此处访问。同样, id 只在 Friend 中可用,而不是在 Hero。
因为 GraphQL 支持 null 可用性,你在编译时就有类型安全保护。如果请求成功,所有查询的数据(也只有这些数据)都将可访问。在 UI 代码中不需要处理 null 字段。
取消
操作 取消是通过 CoroutineScope 处理的。取消当前作用域将取消任何相关的当前 操作。