如何在Android中使用Retrofit和GraphQL?

15
我是新手使用GraphQL,但我已经使用Retrofit有一段时间了,它易于使用和快速。在传递数据方面,GraphQL与rest API有很大的不同。目前关于在Android中使用GraphQL并没有太多教程,我只能找到这个视频(https://www.youtube.com/watch?v=P0uJHI7GjIc&t=1s),但里面没有实际代码。
在我的当前Retrofit调用代码中,我设置了一个端点,如下所示:
final RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(endPoint)
                .build();
        T service = restAdapter.create(clazz);

然后我像这样调用一个REST服务:
@GET("/users/{login}")
    Observable<Github> getUser(@Path("login") String login);

现在使用GraphQL时,您只需要一个基本URL而无需服务路径。此外,如果您查询像userId = 1这样的内容,则必须将其作为Post与Body参数一起发送:

operationName: arbitrary name ,
query: "{users(userid:$userId){username}}, 
variables: "{"userId":1}"

我不确定这如何转换为Retrofit


2
您需要创建一个包含queryoperationNamevariables的JSON主体,然后安排Retrofit将该JSON POST到服务器,到其指定的GraphQL URL。我不确定相对于仅使用OkHttp和Gson来处理GraphQL,Retrofit是否会带来太多好处。 - CommonsWare
好的,我在这里看到如何为Retrofit创建JSON主体:https://dev59.com/YmEi5IYBdhLWcg3wUK6C。但是POST路径应该是什么?即:我只有一个用于Graphql服务器的基本URL。 - Mike6679
2
“但是Post路径应该是什么?” - GraphQL服务器通常只有一个端点。因此,请使用您已经拥有的基本URL,特别是如果它以“/ graphql”结尾。 - CommonsWare
最终我只使用了OkHttp---在这种情况下更简单。 - Mike6679
3个回答

13

构建GraphQL查询和解析响应并不是一件简单的事情。

如果您正在使用此技术进行个人项目开发,我建议开始探索Apollo。这个客户端正在被严格开发,但您可以先了解并体验一下。

https://github.com/apollographql/apollo-android

迄今为止,我喜欢使用Apollo,并且他们在路线图上有很好的功能:RxJava集成、Retrofit、订阅和对AutoValue的支持。


你如何修复Apollo示例应用程序?我只得到HTTP 404或GitHuntFeedActivity:无法解析http响应。 - Hector
3
为什么这是一个答案,它应该是一条评论。 - Angad Singh

9
在您的清单中添加
<uses-permission android:name="android.permission.INTERNET"/>

你的依赖关系

// Kotlin Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.4'

//OkHttp
implementation ("com.squareup.okhttp3:okhttp:3.12.12"){
  force = true //API 19 support
}
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.12'

//retrofit
implementation "com.squareup.retrofit2:retrofit:2.7.1"
implementation "com.squareup.retrofit2:converter-scalars:$2.7.1"

同时兼容Java 8

android {

    ...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}

通过该服务

import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST

interface GraphQLService {

    @Headers("Content-Type: application/json")
    @POST("/")
    suspend fun postDynamicQuery(@Body body: String): Response<String>
}

你可以创建一个对象

import retrofit2.Retrofit
import retrofit2.converter.scalars.ScalarsConverterFactory

object GraphQLInstance {

    private const val BASE_URL: String = "http://192.155.1.55:2000/"

    val graphQLService: GraphQLService by lazy {
        Retrofit
            .Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(ScalarsConverterFactory.create())
            .build().create(GraphQLService::class.java)
    }
}

在活动中,您可以创建此方法。
private fun post(userId: String){
    val retrofit = GraphQLInstance.graphQLService
    val paramObject = JSONObject()
    paramObject.put("query", "query {users(userid:$userId){username}}")
    GlobalScope.launch {
        try {
            val response = retrofit.postDynamicQuery(paramObject.toString())
            Log.e("response", response.body().toString())
        }catch (e: java.lang.Exception){
            e.printStackTrace()
        }
    }
}

你可以查看GitHub上的示例以及我的博文

注意:如果需要进行突变,应更改此行

paramObject.put("query", "query {users(userid:$userId){username}}")

to

paramObject.put("query", "mutation {users(userid:$userId){username}}")

2
我一直收到状态码400 >> 必须提供查询字符串。请问有什么帮助吗? - Amer Hadi
1
你能在你的playground graphQL中检查一下你的查询吗?也许你可以找到错误。 - Cabezas
获取(data=null),请帮忙。 - Aashutosh
我收到了错误信息:GraphQLAuth POST请求中的JSON有效负载无效。curl请求可以正常工作。在Android上,日志显示有效负载有很多反斜杠,例如:"{"query":"query MyQuery {requestOTP(deviceId:\"1cb57166271668b1\", mobilePhone:\"0423130842\") {message}}"}"。 - Rowan Gontier

0

这种方法对我很有效:

interface ApiService {
    @POST("myUrl")
    @Headers("Content-Type: application/json")
    suspend fun requestOtp(@Body requestData: GraphQlRequest): MyResponse
}

data class GraphQlRequest(
    val query: String,
    val variables: Map<String, Any>
)

val query = "query MyQuery { requestOTP(mobilePhone: \"0423130812\" ) { message } }"
val variables = emptyMap<String, Any>()

val request = GraphQlRequest(query, variables)
val apiService = retrofit.create(MyApiService::class.java)
val response = apiService.executeGraphQlQuery(request)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接