为什么是文章
最近,我需要在GraphQL中实现与后端一起使用。与REST不同,在Android上设置的教程并不多,而且大多数教程已不再相关。什么是GraphQL
GraphQL是REST API的时髦替代品,它使您能够以更优化的方式查询数据,仅提供所需的数据。环境设定
我们将通过Apollo向服务器发出请求,Apollo是目前使用GraphQL的最受欢迎的库。让我们开始工作。首先,让我们在清单中添加使用网络所需的权限:<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
接下来,您需要连接阿波罗。我们转到主要的build.gradle并在dependencies部分中添加以下行:classpath 'com.apollographql.apollo:apollo-gradle-plugin:2.0.0'
现在,您需要在应用程序模块的build.gradle文件中添加其他依赖项:implementation("com.apollographql.apollo:apollo-runtime:2.0.0")
implementation "com.apollographql.apollo:apollo-android-support:2.0.0"
另外,将插件连接添加到文件的最顶部:apply plugin: 'com.apollographql.apollo'
同步项目后,我们需要配置模型的代码生成,使用该代码生成查询GraphQL。让我们最小化开发环境并打开一个终端。转到包含项目的文件夹:cd /Users/user/Desktop/ProjectName
如果您还没有npm,请先从官方网站上下载安装apollo-codegen,该工具可让您下载schema.json,该文件将用作生成模型的apollo源:npm install apollo-codegen
下载schema.json(您必须位于项目的目录中,其中出现了node_modules文件夹):node_modules/.bin/apollo-codegen download-schema https:// api/ --output schema.json
现在在项目文件夹中,我们看到了schema.json文件。它仍然显示用于生成模型的阿波罗文件。为此,请执行以下步骤。转到项目的应用程序文件夹,然后转到src-> main。在这里,我们需要创建一个graphQL文件夹。在这里,我们将添加.graphql文件。将上一步下载的文件复制到创建的文件夹-schema.json中。设置环境,转到代码模型代码生成
让我们从.graphql文件开始。请求将存储在这里。GraphQL有两种类型的查询:查询-GET突变的类似物-POST / PUT / DELETE的类似物假设您正在为该酒店的管理员提供将客人入住酒店房间的服务。该应用程序可以执行3个功能。登录用户(管理员),通过ID获取房间信息并填充来宾。在上一节中创建的app / src / main / graphQL目录中创建一个loginUser.graphql文件。使用此文件,apollo将为用户名生成一个模型。档案内容:mutation loginUser($email:String!, $password:String!) {
login(
user: {
email: $email,
password: $password
}
){
email,
token,
refreshToken
}
}
此外,我们需要getRoom.graphql文件,并在其帮助下生成一个模型来获取酒店房间:query getRoom($room_id: String) {
room(room_id: $room_id) {
title,
room_number,
cheked_in_family_name,
has_minibar
}
}
最后的文件是checkUserIn.graphql签入。也使用突变:mutation checkInFamily($room_id: String!, $family_name: String!) {
room(
room: {
title: $family_name,
room_id: $room_id
}
){
room_id,
family_name,
minibar_products{
title,
weight
}
}
}
我们构建项目,并在app / build / generate / source / apollo / debug / service文件夹中看到3个生成的模型:GetRoomQuery,CheckUserInMutation,LoginUserMutation查询执行
创建一个单例NetworkService类,它将为我们提供ApolloClient。我们在其中做两种方法。getApolloClient()执行不需要令牌或任何其他参数的请求,以及getApolloClientWithTokenInterceptor(),我们将令牌放入请求中:import com.apollographql.apollo.ApolloClient
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
class NetworkService {
fun getApolloClient(): ApolloClient {
val okHttp = OkHttpClient
.Builder()
.build()
return ApolloClient.builder()
.serverUrl(BASE_URL)
.okHttpClient(okHttp)
.build()
}
fun getApolloClientWithTokenInterceptor(token: String): ApolloClient {
val httpClient = OkHttpClient.Builder()
.addInterceptor(Interceptor { chain: Interceptor.Chain ->
val original: Request = chain.request()
val builder: Request.Builder = original
.newBuilder()
.method(original.method, original.body)
builder.header("Authorization", "Bearer $token")
return@Interceptor chain.proceed(builder.build())
})
.build()
return ApolloClient.builder()
.serverUrl(BASE_URL)
.okHttpClient(httpClient)
.build()
}
companion object {
private var mInstance: NetworkService? = null
fun getInstance(): NetworkService? {
if (mInstance == null) {
mInstance = NetworkService()
}
return mInstance
}
}
}
现在我们转到活动或片段,在这里我们实现请求的执行。首先,请登录: private fun loginUser() {
val client = NetworkService.getInstance()?.getApolloClient()
val loginMutation = LoginUserMutation
.builder()
.email(emailEdit.text.toString())
.password(passwordEdit.text.toString())
.build()
client
?.mutate(loginMutation)
?.enqueue(object : ApolloCall.Callback<LoginUserMutation.Data>() {
override fun onResponse(response: Response<LoginUserMutation.Data>) {
if (!response.hasErrors()) {
val token = response.data?.login()?.token()
val email = response.data?.login()?.email()
runOnUiThread {
}
}
}
override fun onFailure(e: ApolloException) {}
})
}
这是处理突变的一个例子。我们执行了此请求,但标头中没有令牌。现在,让我们看一个使用查询的示例,尝试获取有关会议室的信息。假设只给代币一个房间。我们执行请求如下: private fun getRoom() {
val token = "123456"
val client = NetworkService.getInstance()
?.getApolloClientWithTokenIntercetor(token)
val roomId = "123"
val allRoomsQuery = GetRoomQuery(Input.fromNullable(roomId))
client
?.query(allRoomsQuery)
?.enqueue(object : ApolloCall.Callback<GetRoomQuery.Data>() {
override fun onResponse(response: Response<GetRoomQuery.Data>) {
if (!response.hasErrors()) {
val familyName = response.data?.room()?.family_name()
}
}
override fun onFailure(e: ApolloException) {}
})
}
作为一项家庭作业,请尝试为自己编写一个解决客人的实施方案。有用的链接:Android的
阿波罗客户端文档Github阿波罗客户端android