Cómo usar los SDKs de Android generados

Los SDKs cliente de Firebase Data Connect te permiten llamar a tus consultas y mutaciones del servidor directamente desde una app de Firebase. Generas un SDK cliente personalizado en paralelo a medida que diseñas los esquemas, las consultas y las mutaciones que implementas en tu servicio de Data Connect. Luego, integras métodos de este SDK en la lógica de tu cliente.

Como mencionamos en otro lugar, es importante tener en cuenta que el código del cliente no envía consultas ni mutaciones, y que estas no se ejecutan en el servidor.Data Connect En cambio, cuando se implementan, las operaciones de Data Connect se almacenan en el servidor, como Cloud Functions. Esto significa que debes implementar los cambios correspondientes del cliente para evitar que se interrumpa la experiencia de los usuarios existentes (por ejemplo, en versiones anteriores de la app).

Por eso, Data Connect te proporciona un entorno de desarrollo y herramientas que te permiten crear prototipos de tus esquemas, consultas y mutaciones implementados en el servidor. También genera automáticamente SDKs del cliente mientras creas prototipos.

Cuando hayas iterado las actualizaciones de tus apps de servicio y cliente, las actualizaciones del servidor y del cliente estarán listas para implementarse.

¿Cuál es el flujo de trabajo de desarrollo de clientes?

Si seguiste la sección Comienza ahora, conociste el flujo de desarrollo general de Data Connect. En esta guía, encontrarás información más detallada para generar SDKs de Android a partir de tu esquema y trabajar con consultas y mutaciones del cliente.

En resumen, para usar los SDK de Android generados en tus apps cliente, deberás seguir estos pasos previos:

  1. Agrega Firebase a tu app para Android.
  2. Configura Data Connect como una dependencia en Gradle.
  3. Agrega el complemento de Gradle de Kotlin Serialization y la dependencia de Gradle.

Luego, haz lo siguiente:

  1. Desarrolla el esquema de tu app.
  2. Configura la generación del SDK:

  3. Inicializa tu código cliente y bibliotecas de importación.

  4. Implementa llamadas a consultas y mutaciones.

  5. Configura y usa el emulador de Data Connect y realiza iteraciones.

Genera tu SDK de Kotlin

Usa la CLI de Firebase para configurar los SDKs generados por Data Connect en tus apps. El comando init debería detectar todas las apps en la carpeta actual y, luego, instalar los SDKs generados automáticamente.

firebase init dataconnect:sdk

Actualiza los SDKs durante la creación de prototipos

Si tienes instalada la extensión de Data Connect para VS Code, siempre mantendrá actualizados los SDKs generados.

Si no usas la extensión de Data Connect para VS Code, puedes usar la CLI de Firebase para mantener actualizados los SDKs generados.

firebase dataconnect:sdk:generate --watch

Genera SDKs en canalizaciones de compilación

Puedes usar Firebase CLI para generar SDKs de Data Connect en los procesos de compilación de CI/CD.

firebase dataconnect:sdk:generate

Configura el código del cliente

Incorpora Data Connect en el código de tu cliente

Para configurar tu código de cliente para usar Data Connect y el SDK generado, primero sigue las instrucciones de configuración estándar de Firebase.

Luego, agrega lo siguiente a la sección plugins en app/build.gradle.kts:

// The Firebase team tests with version 1.8.22; however, other 1.8 versions,
// and all newer versions are expected work too.
kotlin("plugin.serialization") version "1.8.22" // MUST match the version of the Kotlin compiler

Luego, agrega lo siguiente a la sección dependencies en app/build.gradle.kts:

implementation(platform("com.google.firebase:firebase-bom:34.12.0"))
implementation("com.google.firebase:firebase-dataconnect")
implementation("com.google.firebase:firebase-auth") // Optional
implementation("com.google.firebase:firebase-appcheck") // Optional
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // Newer versions should work too
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.5.1") // Newer versions should work too

Inicializa el SDK de Data Connect para Android

Inicializa tu instancia de Data Connect con la información que usaste para configurar Data Connect (toda disponible en la pestaña Data Connect de la consola de Firebase).

El objeto ConnectorConfig

El SDK requiere un objeto de configuración del conector.

Este objeto se genera automáticamente a partir de serviceId y location en dataconnect.yaml, y connectorId en connector.yaml.

Cómo obtener una instancia de conector

Ahora que configuraste un objeto de configuración, obtén una instancia del conector Data Connect. El emulador de Data Connect generará el código de tu conector. Si el nombre del conector es movies y el paquete de Kotlin es com.myapplication, como se especifica en connector.yaml, recupera el objeto del conector llamando a lo siguiente:

val connector = com.myapplication.MoviesConnector.instance

Usa consultas y mutaciones desde tu SDK de Android

Con el objeto del conector, puedes ejecutar consultas y mutaciones según se definen en el código fuente de GraphQL. Supongamos que tu conector tiene definidas estas operaciones:

mutation createMovie($title: String!, $releaseYear: Int!, $genre: String!, $rating: Int!) {
  movie_insert(data: {
    title: $title
    releaseYear: $releaseYear
    genre: $genre
    rating: $rating
  })
}

query getMovieByKey($key: Movie_Key!) {
  movie(key: $key) { id title }
}

query listMoviesByGenre($genre: String!) {
  movies(where: {genre: {eq: $genre}}) {
    id
    title
  }
}

luego, podrías crear y recuperar una película de la siguiente manera:

val connector = MoviesConnector.instance

val addMovieResult1 = connector.createMovie.execute(
  title = "Empire Strikes Back",
  releaseYear = 1980,
  genre = "Sci-Fi",
  rating = 5
)

val movie1 = connector.getMovieByKey.execute(addMovieResult1.data.key)

println("Empire Strikes Back: ${movie1.data.movie}")

También puedes recuperar varias películas:

val connector = MoviesConnector.instance

val addMovieResult2 = connector.createMovie.execute(
  title="Attack of the Clones",
  releaseYear = 2002,
  genre = "Sci-Fi",
  rating = 5
)

val listMoviesResult = connector.listMoviesByGenre.execute(genre = "Sci-Fi")

println(listMoviesResult.data.movies)

También puedes recopilar un Flow que solo producirá un resultado cuando se recupere un nuevo resultado de la búsqueda con una llamada al método execute() de la búsqueda.

val connector = MoviesConnector.instance

connector.listMoviesByGenre.flow(genre = "Sci-Fi").collect { data ->
  println(data.movies)
}

connector.createMovie.execute(
  title="A New Hope",
  releaseYear = 1977,
  genre = "Sci-Fi",
  rating = 5
)

connector.listMoviesByGenre.execute(genre = "Sci-Fi") // will cause the Flow to get notified

Cómo controlar los cambios en los campos de enumeración

El esquema de una app puede contener enumeraciones, a las que se puede acceder con tus consultas de GraphQL.

A medida que cambia el diseño de una app, es posible que agregues nuevos valores admitidos de enumeración. Por ejemplo, imagina que, más adelante en el ciclo de vida de tu aplicación, decides agregar un valor FULLSCREEN al enum AspectRatio.

En el flujo de trabajo de Data Connect, puedes usar herramientas de desarrollo locales para actualizar tus consultas y SDKs.

Sin embargo, antes de lanzar una versión actualizada de tus clientes, es posible que los clientes implementados más antiguos dejen de funcionar.

Ejemplo de implementación resistente

El SDK generado obliga a controlar los valores desconocidos, ya que el código del cliente debe desenvolver el objeto EnumValue, que es EnumValue.Known para los valores de enumeración conocidos o EnumValue.Unknown para los valores desconocidos.

val result = connector.listMoviesByAspectRatio.execute(AspectRatio.WIDESCREEN)
val encounteredAspectRatios = mutableSetOf<String>()

result.data.movies
  .mapNotNull { it.otherAspectRatios }
  .forEach { otherAspectRatios ->
    otherAspectRatios
      .filterNot { it.value == AspectRatio.WIDESCREEN }
      .forEach {
        when (it) {
          is EnumValue.Known -> encounteredAspectRatios.add(it.value.name)
          is EnumValue.Unknown ->
            encounteredAspectRatios.add("[unknown ratio: ${it.stringValue}]")
        }
      }
  }

println(
  "Widescreen movies also include additional aspect ratios: " +
    encounteredAspectRatios.sorted().joinToString()
)

Habilita el almacenamiento en caché del cliente

Data Connect tiene una función de almacenamiento en caché opcional del cliente, que puedes habilitar editando el archivo connector.yaml. Cuando esta función está habilitada, los SDKs de cliente generados almacenan en caché de forma local las respuestas a las consultas, lo que puede reducir la cantidad de solicitudes de bases de datos que realiza tu app y permite que las partes de tu app que dependen de la base de datos funcionen cuando se interrumpe la disponibilidad de la red.

Para habilitar el almacenamiento en caché del cliente, agrega una configuración de almacenamiento en caché del cliente a la configuración del conector:

generate:
  kotlinSdk:
    outputDir: "../android"
    package: "com.google.firebase.dataconnect.generated"
    clientCache:
      maxAge: 5s
      storage: persistent

Esta configuración tiene dos parámetros, ambos opcionales:

  • maxAge: Es la antigüedad máxima que puede tener una respuesta almacenada en caché antes de que el SDK del cliente recupere valores nuevos. Ejemplos: "0", "30s", "1h30m".

    El valor predeterminado de maxAge es 0, lo que significa que las respuestas se almacenan en caché, pero el SDK del cliente siempre recuperará valores nuevos. Los valores almacenados en caché solo se usarán cuando CACHE_ONLY se especifique como execute().

  • storage: El SDK cliente se puede configurar para almacenar en caché las respuestas en el almacenamiento de persistent o en memory. Los resultados almacenados en caché en el almacenamiento de persistent persistirán entre los reinicios de la app. En los SDKs de Android, el valor predeterminado es persistent.

Después de actualizar la configuración de almacenamiento en caché de tu conector, vuelve a generar los SDKs del cliente y a compilar tu app. Una vez que lo hagas, execute() almacenará en caché las respuestas y usará los valores almacenados en caché según la política que configuraste. Por lo general, esto sucede automáticamente, sin que debas realizar ningún paso adicional. Sin embargo, ten en cuenta lo siguiente:

  • El comportamiento predeterminado de execute() es el que se describió anteriormente: si se almacena en caché un resultado para una búsqueda y el valor almacenado en caché no es más antiguo que execute(), se usa el valor almacenado en caché.maxAge Este comportamiento predeterminado se denomina política de PREFER_CACHE.

    También puedes especificar para las invocaciones individuales de execute() que solo se publiquen valores almacenados en caché (CACHE_ONLY) o que se recuperen de forma incondicional valores nuevos del servidor (SERVER_ONLY).

    val queryResult = queryRef.execute(QueryRef.FetchPolicy.CACHE_ONLY)
    
    val queryResult = queryRef.execute(QueryRef.FetchPolicy.SERVER_ONLY)
    

    Crea un prototipo y prueba tu aplicación para Android

    Instrumenta clientes para usar un emulador local

    Puedes usar el emulador de Data Connect, ya sea desde la extensión de Data Connect para VS Code o desde la CLI.

    La instrumentación de la app para conectarse al emulador es la misma en ambos casos.

    val connector = MoviesConnector.instance
    
    // Connect to the emulator on "10.0.2.2:9399"
    connector.dataConnect.useEmulator()
    
    // (alternatively) if you're running your emulator on non-default port:
    connector.dataConnect.useEmulator(port = 9999)
    
    // Make calls from your app
    
    

    Para cambiar a los recursos de producción, comenta las líneas para conectarte al emulador.

    Tipos de datos en los SDK de Data Connect

    El servidor Data Connect representa tipos de datos GraphQL comunes y personalizados. En el SDK, se representan de la siguiente manera.

    Tipo Data Connect Kotlin
    String String
    Int Int (número entero de 32 bits)
    Número de punto flotante Doble (flotante de 64 bits)
    Booleano Booleano
    UUID java.util.UUID
    Fecha com.google.firebase.dataconnect.LocalDate (era java.util.Date hasta la versión 16.0.0-beta03)
    Marca de tiempo com.google.firebase.Timestamp
    Int64 Long
    Cualquiera com.google.firebase.dataconnect.AnyValue