C贸mo configurar Apollo para trabajar con GraphQL en Android

驴Por qu茅 un art铆culo?


Recientemente, tuve la necesidad de implementar el trabajo con un back-end en GraphQL. No hay tantos tutoriales para configurar en Android, a diferencia de REST, y la mayor铆a de ellos ya no son muy relevantes.

驴Qu茅 es GraphQL?


GraphQL es una alternativa moderna a la API REST, que le permite consultar datos de una manera m谩s optimizada, brindando solo los datos que necesita.

Entorno


Realizaremos solicitudes al servidor a trav茅s de Apollo, la biblioteca m谩s popular para trabajar con GraphQL en este momento.

Pong谩monos a trabajar. En primer lugar, agreguemos los permisos necesarios para trabajar con la red al manifiesto:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

A continuaci贸n, debe conectar apollo. Vamos al build.gradle principal y en la secci贸n de dependencias agregamos la siguiente l铆nea:

classpath 'com.apollographql.apollo:apollo-gradle-plugin:2.0.0'

Ahora necesita agregar dependencias adicionales en el archivo build.gradle del m贸dulo de la aplicaci贸n:

implementation("com.apollographql.apollo:apollo-runtime:2.0.0")
implementation "com.apollographql.apollo:apollo-android-support:2.0.0"

Adem谩s, agregue la conexi贸n del complemento a la parte superior del archivo:

apply plugin: 'com.apollographql.apollo'

Despu茅s de sincronizar el proyecto, necesitamos configurar la generaci贸n de c贸digo de los modelos con los que realizaremos consultas a GraphQL.

Minimicemos el entorno de desarrollo y abramos una terminal. Ve a la carpeta con tu proyecto:

cd /Users/user/Desktop/ProjectName

Si a煤n no tiene npm, primero desc谩rguelo del sitio oficial

Instale apollo-codegen, una herramienta que le permite descargar schema.json, un archivo que servir谩 como fuente de apollo para generar modelos:

npm install apollo-codegen

Descargue schema.json (debe estar en el directorio de su proyecto, donde apareci贸 la carpeta node_modules):

node_modules/.bin/apollo-codegen download-schema https://   api/ --output schema.json

Ahora en la carpeta del proyecto vemos el archivo schema.json. Queda por mostrar los archivos Apollo para generar modelos. Para hacer esto, siga los siguientes pasos.

Vaya a la carpeta de la aplicaci贸n de su proyecto, luego src -> main. Aqu铆 necesitamos crear una carpeta graphQL. Aqu铆 agregaremos nuestros archivos .graphql.

Copie el archivo descargado en el paso anterior a la carpeta creada: schema.json
El entorno est谩 configurado , vaya al c贸digo

Generaci贸n de c贸digo modelo


Comencemos con los archivos .graphql. Las solicitudes se almacenar谩n aqu铆.
Hay dos tipos de consultas en GraphQL:
consulta: an谩logo de la
mutaci贸n GET : an谩logo de POST / PUT / DELETE

Suponga que est谩 haciendo un servicio para registrar a los hu茅spedes en una habitaci贸n de un hotel para los administradores de este hotel. La aplicaci贸n puede hacer 3 funciones. Inicie sesi贸n con el usuario (administrador), obtenga informaci贸n sobre la sala por id y

complete los invitados Cree el archivo loginUser.graphql en el directorio app / src / main / graphQL creado en la secci贸n anterior. Al usar este archivo, Apollo generar谩 un modelo para el nombre de usuario.

Contenido del archivo:

mutation loginUser($email:String!, $password:String!) {
    login(
        user: {
            email: $email,
            password: $password
        }
    ){
        email,
        token,
        refreshToken
    }
}

Adem谩s, necesitamos el archivo getRoom.graphql, con su ayuda se genera un modelo para obtener la habitaci贸n del hotel:

query getRoom($room_id: String) {
    room(room_id: $room_id) {
        title,
        room_number,
        cheked_in_family_name,
        has_minibar
    }
}

Y el archivo final es checkUserIn.graphql check-in. Tambi茅n usa mutaci贸n:

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
        }
    }
}

Construimos el proyecto y vemos 3 modelos generados en la carpeta app / build / generate / source / apollo / debug / service: GetRoomQuery, CheckUserInMutation, LoginUserMutation

Ejecuci贸n de la consulta


Cree una clase Singleton NetworkService que nos proporcionar谩 ApolloClient. Hacemos 2 m茅todos en 茅l. getApolloClient () para ejecutar solicitudes que no requieren un token o ning煤n par谩metro adicional, y getApolloClientWithTokenInterceptor (), en el que arrojaremos el token, para solicitudes:

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
    }
  }
}

Ahora vamos a nuestra actividad o fragmento, aqu铆 implementamos la ejecuci贸n de solicitudes. Para comenzar, inicie sesi贸n:

  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()
            // ,   ui,     
            runOnUiThread {
              //   ,  
            }
          }
        }

        override fun onFailure(e: ApolloException) {}
      })
  }

Este es un ejemplo de trabajo con mutaci贸n. Realizamos esta solicitud sin un token en el encabezado. Ahora veamos un ejemplo de trabajo con consulta, intente obtener informaci贸n sobre la sala. Supongamos que se nos da una habitaci贸n solo con una ficha. Ejecutamos la solicitud de la siguiente manera:

  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) {}
      })
  }

Como tarea, intente redactarse una implementaci贸n de establecimiento de invitados.

Enlaces 煤tiles:

documentaci贸n de apollo-client para Android
Github apollo-client android

All Articles