Użyj wygenerowanych pakietów SDK na Androida

Firebase SQL Connect pakiety SDK klienta umożliwiają wywoływanie zapytań i mutacji po stronie serwera bezpośrednio z aplikacji w Firebase. Podczas projektowania schematów, zapytań i mutacji, które wdrażasz w usłudze SQL Connect równolegle generujesz niestandardowy pakiet SDK klienta. Następnie integrujesz metody z tego pakietu SDK z logiką klienta.

Jak już wspominaliśmy, ważne jest, aby pamiętać, że SQL Connect zapytania i mutacje nie są przesyłane przez kod klienta i wykonywane na serwerze. Zamiast tego po wdrożeniu operacje SQL Connect są przechowywane na serwerze, tak jak Cloud Functions. Oznacza to, że musisz wdrożyć odpowiednie zmiany po stronie klienta, aby uniknąć problemów u dotychczasowych użytkowników (np. w starszych wersjach aplikacji).

Dlatego SQL Connect udostępnia środowisko programistyczne i narzędzia, które umożliwiają tworzenie prototypów schematów, zapytań i mutacji wdrożonych na serwerze. Podczas tworzenia prototypu automatycznie generuje też pakiety SDK po stronie klienta.

Gdy wprowadzisz iteracyjne aktualizacje usługi i aplikacji klienckich, aktualizacje po stronie serwera i klienta będą gotowe do wdrożenia.

Jak wygląda proces tworzenia aplikacji klienckiej?

Jeśli wykonasz czynności opisane w przewodniku Pierwsze kroki, poznasz ogólny proces tworzenia aplikacji za pomocą SQL Connect. W tym przewodniku znajdziesz bardziej szczegółowe informacje o generowaniu pakietów SDK na Androida na podstawie schematu oraz o pracy z zapytaniami i mutacjami klienta.

Podsumowując, aby używać wygenerowanych pakietów SDK na Androida w aplikacjach klienckich, wykonaj te czynności przygotowawcze:

  1. Dodaj Firebase do aplikacji na Androida.
  2. Skonfiguruj SQL Connect jako zależność w Gradle.
  3. Dodaj wtyczkę Gradle do serializacji w Kotlinie i zależność Gradle.

Następnie:

  1. Opracuj schemat aplikacji.
  2. Skonfiguruj generowanie pakietu SDK:

    • Za pomocą przycisku Dodaj pakiet SDK do aplikacji w rozszerzeniu SQL Connect VS Code.
    • Aktualizując plik connector.yaml
  3. Zainicjuj kod klienta i zaimportuj biblioteki.

  4. Zaimplementuj wywołania zapytań i mutacji.

  5. Skonfiguruj emulator SQL Connect i używaj go i iteruj.

Generowanie pakietu SDK w Kotlinie

Użyj interfejsu wiersza poleceń Firebase, aby skonfigurować wygenerowane pakiety SDK SQL Connect w aplikacjach. Polecenie init powinno wykryć wszystkie aplikacje w bieżącym folderze i automatycznie zainstalować wygenerowane pakiety SDK.

firebase init dataconnect:sdk

Aktualizowanie pakietów SDK podczas tworzenia prototypu

Jeśli masz zainstalowane rozszerzenie SQL Connect VS Code, będzie ono zawsze aktualizować wygenerowane pakiety SDK.

Jeśli nie używasz rozszerzenia SQL Connect VS Code, możesz użyć wiersza poleceń Firebase, aby aktualizować wygenerowane pakiety SDK.

firebase dataconnect:sdk:generate --watch

Generowanie pakietów SDK w potokach kompilacji

Za pomocą wiersza poleceń Firebase możesz generować pakiety SDK SQL Connect w procesach kompilacji CI/CD.

firebase dataconnect:sdk:generate

Konfigurowanie kodu klienta

Włączanie SQL Connect w kodzie klienta

Aby skonfigurować kod klienta do używania SQL Connect i wygenerowanego pakietu SDK, najpierw wykonaj standardowe instrukcje konfiguracji Firebase.

Następnie dodaj te wiersze do sekcji plugins w pliku 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

Następnie dodaj te wiersze do sekcji dependencies w pliku app/build.gradle.kts:

implementation(platform("com.google.firebase:firebase-bom:34.13.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

Inicjowanie pakietu Android SDKSQL Connect

Zainicjuj instancję SQL Connect, używając informacji, których używasz do konfigurowania SQL Connect. Te informacje znajdziesz w Bazach danych i miejscu na dane > SQL Connect na stronie konsoli Firebase.

Obiekt ConnectorConfig

Pakiet SDK wymaga obiektu konfiguracji oprogramowania sprzęgającego.

Ten obiekt jest generowany automatycznie na podstawie wartości serviceId i location w pliku dataconnect.yaml oraz connectorId w pliku connector.yaml.

Uzyskiwanie instancji oprogramowania sprzęgającego

Gdy skonfigurujesz obiekt konfiguracji, uzyskaj instancję oprogramowania sprzęgającego SQL Connect. Kod oprogramowania sprzęgającego zostanie wygenerowany przez emulator SQL Connect. Jeśli nazwa oprogramowania sprzęgającego to movies, a pakiet Kotlin to com.myapplication (zgodnie z plikiem connector.yaml), pobierz obiekt oprogramowania sprzęgającego, wywołując:

val connector = com.myapplication.MoviesConnector.instance

Używanie zapytań i mutacji z pakietu Android SDK

Za pomocą obiektu oprogramowania sprzęgającego możesz uruchamiać zapytania i mutacje zdefiniowane w kodzie źródłowym GraphQL. Załóżmy, że oprogramowanie sprzęgające ma zdefiniowane te operacje:

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

Wtedy możesz utworzyć i pobrać film w ten sposób:

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

Możesz też pobrać kilka filmów:

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)

Możesz też zebrać Flow, który będzie generować wynik tylko wtedy, gdy nowy wynik zapytania zostanie pobrany za pomocą wywołania metody execute() zapytania.

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

Obsługa zmian w polach wyliczeniowych

Schemat aplikacji może zawierać wyliczenia, do których można uzyskać dostęp za pomocą zapytań GraphQL.

W miarę zmian w projekcie aplikacji możesz dodawać nowe obsługiwane wartości wyliczeniowe. Wyobraź sobie na przykład, że w późniejszym etapie cyklu życia aplikacji zdecydujesz się dodać wartość FULLSCREEN do wyliczenia AspectRatio.

W procesie SQL Connect możesz używać lokalnych narzędzi programistycznych do aktualizowania zapytań i pakietów SDK.

Zanim jednak opublikujesz zaktualizowaną wersję klientów, starsze wdrożone klienty mogą przestać działać.

Przykład odpornej implementacji

Wygenerowany pakiet SDK wymusza obsługę nieznanych wartości, ponieważ kod klienta musi rozpakować obiekt EnumValue, który może mieć wartość EnumValue.Known w przypadku znanych wartości wyliczeniowych lub EnumValue.Unknown w przypadku nieznanych wartości.

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

Włączanie buforowania po stronie klienta

SQL Connect ma opcjonalną funkcję buforowania po stronie klienta, którą możesz włączyć, edytując plik connector.yaml. Gdy ta funkcja jest włączona, wygenerowane pakiety SDK klienta będą lokalnie buforować odpowiedzi na zapytania, co może zmniejszyć liczbę zapytań do bazy danych wysyłanych przez aplikację i umożliwić działanie części aplikacji zależnych od bazy danych, gdy sieć jest niedostępna.

Aby włączyć buforowanie po stronie klienta, dodaj konfigurację buforowania po stronie klienta do konfiguracji oprogramowania sprzęgającego:

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

Ta konfiguracja ma 2 parametry, oba opcjonalne:

  • maxAge: maksymalny wiek buforowanej odpowiedzi, po którym pakiet SDK klienta pobiera nowe wartości. Przykłady: „0”, „30s”, „1h30m”.

    Domyślna wartość maxAge to 0, co oznacza, że odpowiedzi są buforowane, ale pakiet SDK klienta zawsze pobiera nowe wartości. Buforowane wartości będą używane tylko wtedy, gdy w przypadku execute() zostanie określona wartość CACHE_ONLY.

  • storage: pakiet SDK klienta można skonfigurować tak, aby buforował odpowiedzi w pamięci persistent lub memory. Wyniki buforowane w pamięci persistent będą zachowywane po ponownym uruchomieniu aplikacji. W pakietach SDK na Androida domyślnie używana jest pamięć persistent.

Po zaktualizowaniu konfiguracji buforowania oprogramowania sprzęgającego wygeneruj ponownie pakiety SDK klienta i ponownie skompiluj aplikację. Gdy to zrobisz, execute() będzie buforować odpowiedzi i używać buforowanych wartości zgodnie ze skonfigurowanymi zasadami. Zwykle dzieje się to automatycznie, bez żadnych dodatkowych działań z Twojej strony. Pamiętaj jednak o tych kwestiach:

  • Domyślne działanie funkcji execute() jest takie, jak opisano powyżej: jeśli wynik jest buforowany dla zapytania, a buforowana wartość nie jest starsza niż maxAge, użyj buforowanej wartości. To domyślne działanie jest nazywane zasadą PREFER_CACHE.

    Możesz też określić, że poszczególne wywołania funkcji execute() mają używać tylko buforowanych wartości (CACHE_ONLY) lub bezwarunkowo pobierać nowe wartości z serwera (SERVER_ONLY).

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

    Tworzenie prototypu i testowanie aplikacji na Androida

    Instrumentowanie klientów do używania lokalnego emulatora

    Możesz używać emulatora SQL Connect w rozszerzeniu SQL Connect VS Code lub w interfejsie wiersza poleceń.

    Konfigurowanie aplikacji do łączenia się z emulatorem jest takie samo w obu przypadkach.

    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
    
    

    Aby przełączyć się na zasoby produkcyjne, zakomentuj wiersze służące do łączenia się z emulatorem.

    Typy SQL w pakietach SDK SQL Connect

    Serwer SQL Connect reprezentuje standardowe i niestandardowe typy danych GraphQL. Są one reprezentowane w pakiecie SDK w ten sposób.

    SQL Connect Typ Kotlin
    Ciąg znaków Ciąg znaków
    Liczba całkowita Liczba całkowita (32-bitowa)
    Liczba zmiennoprzecinkowa Double (liczba zmiennoprzecinkowa 64-bitowa)
    Wartość logiczna Wartość logiczna
    UUID java.util.UUID
    Data com.google.firebase.dataconnect.LocalDate (do wersji 16.0.0-beta03 był to typ java.util.Date)
    Sygnatura czasowa com.google.firebase.Timestamp
    Int64 Long
    Dowolna com.google.firebase.dataconnect.AnyValue