-
Notifications
You must be signed in to change notification settings - Fork 19
Getting Started
Create a retrofit interface method and annotate them with the @GraphQuery
annotation using the name of the .graphql
file name as the value parameter. e.g.
internal enum class EndpointType(val url: HttpUrl) {
GITHUB(BuildConfig.github.toHttpUrl()),
BUCKET(BuildConfig.bucket.toHttpUrl());
companion object {
const val BASE_ENDPOINT_PATH = "/graphql"
}
}
internal interface MarketPlaceRemoteSource {
@POST(EndpointType.BASE_ENDPOINT_PATH)
@GraphQuery("GetMarketPlaceApps")
suspend fun getMarketPlaceApps(
@Body builder: QueryContainerBuilder
): Response<GraphContainer<MarketPlaceListings>>
}
The model creation is up to the developer, this is where retrofit-graphql
differs from apollo
, this way you can design your models in anyway you desire.
There are tools available to aid in the task of creating models from JSON.
For Kotlin there is JSON To Kotlin Class, a plugin for the IDEA product family. There are also numerous tools available online e.g jsonschema2pojo. One can always start from there and then modify the automatically generated output.
By default the library supplies you with a QueryContainerBuilder
which is a holder for your GraphQL variables, operations and request. Also two basic top level models, which you don't have to use if you want to design your own:
Suggest using this as is, but if you want to make your own that's not a problem either. The QueryContainerBuilder is used as follows:
Given a .graphql files such as the following:
query GetMarketPlaceApps($first: Int, $after: String, $before: String) {
marketplaceListings(first: $first, after: $after, before: $before) {
edges {
cursor
node {
... MarketPlaceListingCore
}
}
pageInfo {
... PageInfo
}
totalCount
}
}
Adding parameters to the request would be done as follows:
val queryBuilder = QueryContainerBuilder()
.putVariable("first", 15)
// or alternatively you can add a map
val queryBuilder = QueryContainerBuilder()
.putVariables(
mapOf(
"first" to 15,
"after" to "some_cursor_id"
)
)
The QueryContainerBuilder
is then passed into your retrofit interface method as a parameter and that's it! Just like you would with any ordinary retrofit method.
Common GraphQL error that makes use of extension functions
/**
* Converts the response error response into an object.
*
* @return The error object, or null if an exception was encountered
*
* @see GraphError
*/
fun Response<*>?.getError(): List<GraphError>? {
try {
if (this != null) {
val responseBody = errorBody()
val message = responseBody?.string()
if (responseBody != null && !message.isNullOrBlank()) {
val graphErrors= message.getGraphQLError()
if (graphErrors != null)
return graphErrors
}
}
} catch (ex: Exception) {
ex.printStackTrace()
}
return null
}
@Throws(JsonSyntaxException::class)
private fun String.getGraphQLError(): List<GraphError>? {
val tokenType = object : TypeToken<GraphContainer<*>>() {}.type
val graphContainer = Gson().fromJson<GraphContainer<*>>(this, tokenType)
return graphContainer.errors
}
Similar to the top level GraphQL response, but the data type is generic to allow easy reuse.
data class GraphContainer<T>(
val data: T? = null,
val errors: List<GraphError>? = null,
val extensions: Map<Any, Any>? = null
)