Generierte Android-SDKs verwenden

Mit den Firebase SQL Connect Client-SDKs können Sie Ihre serverseitigen Abfragen und Mutationen direkt über eine Firebase-App aufrufen. Sie generieren parallel ein benutzerdefiniertes Client-SDK, während Sie die Schemas, Abfragen und Mutationen entwerfen, die Sie in Ihrem SQL Connect Dienst bereitstellen. Anschließend binden Sie Methoden aus diesem SDK in Ihre Clientlogik ein.

Wie bereits erwähnt, ist es wichtig zu beachten, dass SQL Connect Abfragen und Mutationen nicht vom Clientcode gesendet und auf dem Server ausgeführt werden. Stattdessen werden SQL Connect Vorgänge nach der Bereitstellung wie Cloud Functions auf dem Server gespeichert. Das bedeutet, dass Sie entsprechende clientseitige Änderungen bereitstellen müssen, um Probleme für bestehende Nutzer zu vermeiden (z. B. bei älteren App-Versionen).

Aus diesem Grund bietet SQL Connect eine Entwicklungsumgebung und Tools, mit denen Sie Prototypen für Ihre serverseitig bereitgestellten Schemas, Abfragen und Mutationen erstellen können. Außerdem werden während der Prototyperstellung automatisch clientseitige SDKs generiert.

Nachdem Sie die Updates für Ihre Dienst- und Client-Apps durchlaufen haben, können sowohl serverseitige als auch clientseitige Updates bereitgestellt werden.

Was ist der Workflow für die Cliententwicklung?

Wenn Sie die Anleitung Erste Schritte befolgt haben, haben Sie bereits den allgemeinen Entwicklungsablauf für SQL Connect kennengelernt. In dieser Anleitung finden Sie detailliertere Informationen zum Generieren von Android-SDKs aus Ihrem Schema und zum Arbeiten mit Clientabfragen und -mutationen.

Zusammenfassend lässt sich sagen, dass Sie die folgenden Schritte ausführen müssen, um generierte Android-SDKs in Ihren Client-Apps zu verwenden:

  1. Firebase zu Ihrer Android App hinzufügen
  2. SQL Connect als Abhängigkeit in Gradle konfigurieren
  3. Gradle-Plug‑in und Gradle-Abhängigkeit für die Kotlin-Serialisierung hinzufügen

Gehen Sie anschließend so vor:

  1. App-Schema entwickeln
  2. SDK-Generierung einrichten:

  3. Clientcode initialisieren und Bibliotheken importieren.

  4. Aufrufe für Abfragen und Mutationen implementieren.

  5. Richten Sie den SQL Connect Emulator ein und verwenden Sie ihn, und führen Sie Iterationen durch.

Kotlin-SDK generieren

Verwenden Sie die Firebase CLI, um generierte SQL Connect SDKs in Ihren Apps einzurichten. Mit dem Befehl init sollten alle Apps im aktuellen Ordner erkannt und generierte SDKs automatisch installiert werden.

firebase init dataconnect:sdk

SDKs während der Prototyperstellung aktualisieren

Wenn Sie die SQL Connect VS Code-Erweiterung installiert haben, werden generierte SDKs immer auf dem neuesten Stand gehalten.

Wenn Sie die SQL Connect VS Code-Erweiterung nicht verwenden, können Sie generierte SDKs mit der Firebase CLI auf dem neuesten Stand halten.

firebase dataconnect:sdk:generate --watch

SDKs in Build-Pipelines generieren

Mit der Firebase CLI können Sie SQL Connect SDKs in CI/CD-Build-Prozessen generieren.

firebase dataconnect:sdk:generate

Clientcode einrichten

SQL Connect in Clientcode einbinden

Wenn Sie Ihren Clientcode für die Verwendung von SQL Connect und Ihrem generierten SDK, einrichten möchten, folgen Sie zuerst der Standardanleitung für die Firebase-Einrichtung.

Fügen Sie dann Folgendes in den Abschnitt plugins in app/build.gradle.kts ein:

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

Fügen Sie dann Folgendes in den Abschnitt dependencies in app/build.gradle.kts ein:

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

SQL Connect Android SDK initialisieren

Initialisieren Sie Ihre SQL Connect-Instanz mit den Informationen, die Sie zum Einrichten von SQL Connect verwendet haben (alle auf dem Tab „SQL Connect“ in der Firebase Console verfügbar).

Das ConnectorConfig-Objekt

Für das SDK ist ein Connector-Konfigurationsobjekt erforderlich.

Dieses Objekt wird automatisch aus serviceId und location in dataconnect.yaml und connectorId in connector.yaml generiert.

Connector-Instanz abrufen

Nachdem Sie ein Konfigurationsobjekt eingerichtet haben, rufen Sie eine SQL Connect Connector-Instanz ab. Der Code für Ihren Connector wird vom SQL Connect Emulator generiert. Wenn Ihr Connector-Name movies und das Kotlin-Paket com.myapplication ist, wie in connector.yaml angegeben, rufen Sie das Connector-Objekt mit folgendem Aufruf ab:

val connector = com.myapplication.MoviesConnector.instance

Abfragen und Mutationen aus Ihrem Android-SDK verwenden

Mit dem Connector-Objekt können Sie Abfragen und Mutationen ausführen, wie im GraphQL-Quellcode definiert. Angenommen, für Ihren Connector sind die folgenden Vorgänge definiert:

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

Dann können Sie einen Film so erstellen und abrufen:

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

Sie können auch mehrere Filme abrufen:

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)

Sie können auch einen Flow erfassen, der nur dann ein Ergebnis liefert, wenn ein neues Abfrageergebnis mit einem Aufruf der execute()-Methode der Abfrage abgerufen wird.

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

Änderungen an Aufzählungsfeldern verarbeiten

Das Schema einer App kann Aufzählungen enthalten, auf die mit GraphQL-Abfragen zugegriffen werden kann.

Wenn sich das Design einer App ändert, können Sie neue unterstützte Aufzählungswerte hinzufügen. Angenommen, Sie entscheiden sich später im Lebenszyklus Ihrer Anwendung, der Aufzählung AspectRatio den Wert FULLSCREEN hinzuzufügen.

Im SQL Connect Workflow können Sie lokale Entwicklungstools verwenden, um Ihre Abfragen und SDKs zu aktualisieren.

Bevor Sie jedoch eine aktualisierte Version Ihrer Clients veröffentlichen, können ältere bereitgestellte Clients Probleme verursachen.

Beispiel für eine robuste Implementierung

Das generierte SDK erzwingt die Verarbeitung unbekannter Werte, da der Code des Kunden das EnumValue Objekt entpacken muss. Dieses ist entweder EnumValue.Known für bekannte Aufzählungswerte oder EnumValue.Unknown für unbekannte Werte.

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

Clientseitiges Caching aktivieren

SQL Connect bietet eine optionale clientseitige Caching-Funktion, die Sie aktivieren können, indem Sie die Datei connector.yaml bearbeiten. Wenn diese Funktion aktiviert ist, werden Abfrageantworten von den generierten Client-SDKs lokal im Cache gespeichert. Dadurch kann die Anzahl der Datenbankanfragen Ihrer App reduziert werden und die datenbankabhängigen Teile Ihrer App funktionieren auch dann, wenn die Netzwerkverfügbarkeit unterbrochen ist.

Wenn Sie das clientseitige Caching aktivieren möchten, fügen Sie Ihrer Connector-Konfiguration eine Client-Caching-Konfiguration hinzu:

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

Diese Konfiguration hat zwei Parameter, die beide optional sind:

  • maxAge: Das maximale Alter einer im Cache gespeicherten Antwort, bevor das Client-SDK neue Werte abruft. Beispiele: „0“, „30s“, „1h30m“

    Der Standardwert für maxAge ist 0. Das bedeutet, dass Antworten im Cache gespeichert werden, das Client-SDK aber immer neue Werte abruft. Die im Cache gespeicherten Werte werden nur verwendet, wenn für execute() die Option CACHE_ONLY angegeben ist.

  • storage: Das Client-SDK kann so konfiguriert werden, dass Antworten entweder im persistent-Speicher oder im memory-Speicher im Cache gespeichert werden. Im persistent-Speicher im Cache gespeicherte Ergebnisse bleiben auch nach einem Neustart der App erhalten. In Android-SDKs ist persistent die Standardeinstellung.

Nachdem Sie die Caching-Konfiguration Ihres Connectors aktualisiert haben, generieren Sie Ihre Client SDKs neu und erstellen Sie Ihre App neu. Danach werden Antworten von execute() im Cache gespeichert und im Cache gespeicherte Werte gemäß der konfigurierten Richtlinie verwendet. Das geschieht in der Regel automatisch, ohne dass Sie dafür noch etwas tun müssen. Beachten Sie jedoch Folgendes:

  • Das Standardverhalten von execute() ist wie oben beschrieben: Wenn ein Ergebnis für eine Abfrage im Cache gespeichert ist und der im Cache gespeicherte Wert nicht älter als maxAge ist, wird der im Cache gespeicherte Wert verwendet. Dieses Standardverhalten wird als PREFER_CACHE-Richtlinie bezeichnet.

    Sie können auch für einzelne Aufrufe von execute() angeben, dass entweder nur im Cache gespeicherte Werte bereitgestellt werden (CACHE_ONLY) oder dass bedingungslos neue Werte vom Server abgerufen werden (SERVER_ONLY).

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

    Prototyp erstellen und Android-App testen

    Clients für die Verwendung eines lokalen Emulators instrumentieren

    Sie können den SQL Connect Emulator verwenden, entweder über die SQL Connect VS Code-Erweiterung oder über die CLI.

    Die Instrumentierung der App für die Verbindung zum Emulator ist in beiden Fällen gleich.

    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
    
    

    Wenn Sie zu Produktionsressourcen wechseln möchten, kommentieren Sie die Zeilen für die Verbindung zum Emulator aus.

    SQL-Typen in SQL Connect SDKs

    Der SQL Connect Server stellt allgemeine und benutzerdefinierte GraphQL-Daten typen dar. Diese werden im SDK so dargestellt:

    SQL Connect Typ Kotlin
    String String
    Int Int (32-Bit-Ganzzahl)
    Float Double (64-Bit-Gleitkommazahl)
    Boolean Boolean
    UUID java.util.UUID
    Date com.google.firebase.dataconnect.LocalDate (bis Version 16.0.0-beta03 java.util.Date)
    Timestamp com.google.firebase.Timestamp
    Int64 Long
    Any com.google.firebase.dataconnect.AnyValue