Usa gli SDK Android generati

Gli SDK client Firebase Data Connect ti consentono di chiamare le query e le mutazioni lato server direttamente da un'app Firebase. Generi un SDK client personalizzato in parallelo alla progettazione degli schemi, delle query e delle mutazioni che implementi nel tuo servizio Data Connect. Poi, integra i metodi di questo SDK nella logica del client.

Come abbiamo già detto, è importante notare che Data Connect le query e le mutazioni non vengono inviate dal codice client ed eseguite sul server. Al contrario, quando viene eseguito il deployment, le operazioni Data Connect vengono archiviate sul server come Cloud Functions. Ciò significa che devi implementare le modifiche lato client corrispondenti per evitare di interrompere l'esperienza degli utenti esistenti (ad esempio, nelle versioni precedenti dell'app).

Per questo motivo, Data Connect ti fornisce un ambiente di sviluppo e strumenti che ti consentono di creare prototipi di schemi, query e mutazioni implementati sul server. Inoltre, genera automaticamente gli SDK lato client durante la prototipazione.

Una volta completate le iterazioni degli aggiornamenti del servizio e delle app client, gli aggiornamenti lato server e lato client sono pronti per il deployment.

Che cos'è il flusso di lavoro di sviluppo del client?

Se hai seguito la guida Inizia, hai appreso il flusso di sviluppo complessivo per Data Connect. In questa guida troverai informazioni più dettagliate sulla generazione di SDK Android dallo schema e sull'utilizzo di query e mutazioni client.

Per riassumere, per utilizzare gli SDK Android generati nelle tue app client, segui questi passaggi preliminari:

  1. Aggiungi Firebase alla tua app Android.
  2. Configura Data Connect come dipendenza in Gradle.
  3. Aggiungi il plug-in Gradle per la serializzazione Kotlin e la dipendenza Gradle.

Quindi:

  1. Sviluppa lo schema dell'app.
  2. Configura la generazione dell'SDK:

  3. Inizializza il codice client e importa le librerie.

  4. Implementa le chiamate a query e mutazioni.

  5. Configura e utilizza l'Data Connect emulatore e itera.

Genera l'SDK Kotlin

Utilizza la CLI Firebase per configurare gli SDK generati da Data Connect nelle tue app. Il comando init deve rilevare tutte le app nella cartella corrente e installare automaticamente gli SDK generati.

firebase init dataconnect:sdk

Aggiornare gli SDK durante la prototipazione

Se hai installato l'estensione Data Connect VS Code, manterrà sempre aggiornati gli SDK generati.

Se non utilizzi l'estensione VS Code di Data Connect, puoi utilizzare l'interfaccia a riga di comando di Firebase per mantenere aggiornati gli SDK generati.

firebase dataconnect:sdk:generate --watch

Genera SDK nelle pipeline di build

Puoi utilizzare l'interfaccia a riga di comando di Firebase per generare SDK Data Connect nei processi di build CI/CD.

firebase dataconnect:sdk:generate

Configurare il codice cliente

Incorporare Data Connect nel codice cliente

Per configurare il codice client in modo che utilizzi Data Connect e l'SDK generato, segui innanzitutto le istruzioni di configurazione standard di Firebase.

Poi, aggiungi quanto segue alla sezione plugins in 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

Poi, aggiungi quanto segue alla sezione dependencies in 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

Inizializza l'SDK Android Data Connect

Inizializza l'istanza Data Connect utilizzando le informazioni che hai utilizzato per configurare Data Connect (tutte disponibili nella scheda Data Connect della console Data Connect).Firebase

L'oggetto ConnectorConfig

L'SDK richiede un oggetto di configurazione del connettore.

Questo oggetto viene generato automaticamente da serviceId e location in dataconnect.yaml e connectorId in connector.yaml.

Recupero di un'istanza del connettore

Ora che hai configurato un oggetto di configurazione, ottieni un'istanza del connettore Data Connect. Il codice per il connettore verrà generato dall'emulatore Data Connect. Se il nome del connettore è movies e il pacchetto Kotlin è com.myapplication, come specificato in connector.yaml, recupera l'oggetto connettore chiamando:

val connector = com.myapplication.MoviesConnector.instance

Utilizzare query e mutazioni dall'SDK Android

Con l'oggetto connettore, puoi eseguire query e mutazioni come definito nel codice sorgente GraphQL. Supponiamo che il connettore abbia definito le seguenti operazioni:

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

potresti creare e recuperare un filmato nel seguente modo:

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

Puoi anche recuperare più film:

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)

Puoi anche raccogliere un Flow che produrrà un risultato solo quando viene recuperato un nuovo risultato della query utilizzando una chiamata al metodo execute() della query.

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

Gestire le modifiche ai campi di enumerazione

Lo schema di un'app può contenere enumerazioni, a cui è possibile accedere tramite le query GraphQL.

Man mano che il design di un'app cambia, puoi aggiungere nuovi valori enum supportati. Ad esempio, immagina di decidere di aggiungere un valore FULLSCREEN all'enumerazione AspectRatio in un secondo momento del ciclo di vita della tua applicazione.

Nel flusso di lavoro Data Connect, puoi utilizzare gli strumenti di sviluppo locali per aggiornare le query e gli SDK.

Tuttavia, prima di rilasciare una versione aggiornata dei client, i client meno recenti potrebbero non funzionare.

Esempio di implementazione resiliente

L'SDK generato impone la gestione dei valori sconosciuti, poiché il codice del cliente deve estrarre l'oggetto EnumValue, che è EnumValue.Known per i valori enum noti o EnumValue.Unknown per i valori sconosciuti.

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()
)

Abilita la memorizzazione nella cache lato client

Data Connect ha una funzionalità di memorizzazione nella cache lato client facoltativa, che puoi attivare modificando il file connector.yaml. Quando questa funzionalità è abilitata, gli SDK client generati memorizzano nella cache locale le risposte alle query, il che può ridurre il numero di richieste al database effettuate dalla tua app e consente alle parti dell'app che dipendono dal database di funzionare quando la disponibilità di rete è interrotta.

Per attivare la memorizzazione nella cache lato client, aggiungi una configurazione della memorizzazione nella cache lato client alla configurazione del connettore:

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

Questa configurazione ha due parametri, entrambi facoltativi:

  • maxAge: l'età massima di una risposta memorizzata nella cache prima che l'SDK client recuperi valori aggiornati. Esempi: "0", "30s", "1h30m".

    Il valore predefinito per maxAge è 0, il che significa che le risposte vengono memorizzate nella cache, ma l'SDK client recupererà sempre valori aggiornati. I valori memorizzati nella cache verranno utilizzati solo quando CACHE_ONLY è impostato su execute().

  • storage: l'SDK client può essere configurato per memorizzare nella cache le risposte nello spazio di archiviazione persistent o in memory. I risultati memorizzati nella cache nello spazio di archiviazione persistent rimarranno disponibili anche dopo il riavvio dell'app. Negli SDK Android, il valore predefinito è persistent.

Dopo aver aggiornato la configurazione della memorizzazione nella cache del connettore, rigenera gli SDK client e ricompila l'app. Una volta fatto, execute() memorizzerà nella cache le risposte e utilizzerà i valori memorizzati nella cache in base alle norme che hai configurato. In genere questo avviene automaticamente, senza ulteriori interventi da parte tua; tuttavia, tieni presente quanto segue:

  • Il comportamento predefinito di execute() è quello descritto sopra: se un risultato viene memorizzato nella cache per una query e il valore memorizzato nella cache non è precedente a maxAge, utilizza il valore memorizzato nella cache. Questo comportamento predefinito è chiamato criterio PREFER_CACHE.

    Puoi anche specificare le singole chiamate di execute() per servire solo i valori memorizzati nella cache (CACHE_ONLY) o per recuperare in modo incondizionato i valori aggiornati dal server (SERVER_ONLY).

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

    Prototipare e testare l'app per Android

    Strumentare i client per utilizzare un emulatore locale

    Puoi utilizzare l'emulatore Data Connect, sia dall'estensione VS Code Data Connect sia dalla CLI.

    L'instrumentazione dell'app per la connessione all'emulatore è la stessa per entrambi gli scenari.

    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
    
    

    Per passare alle risorse di produzione, commenta le righe per la connessione all'emulatore.

    Tipi di dati negli SDK Data Connect

    Il server Data Connect rappresenta i tipi di dati GraphQL comuni e personalizzati. Questi sono rappresentati nell'SDK come segue.

    Tipo di Data Connect Kotlin
    Stringa Stringa
    Int Int (intero a 32 bit)
    In virgola mobile Double (virgola mobile a 64 bit)
    Booleano Booleano
    UUID java.util.UUID
    Data com.google.firebase.dataconnect.LocalDate (era java.util.Date fino alla versione 16.0.0-beta03)
    Timestamp com.google.firebase.Timestamp
    Int64 Lungo
    Qualsiasi com.google.firebase.dataconnect.AnyValue