Użyj wygenerowanych pakietów SDK na Androida

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

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

Dlatego SQL Connect udostępnia środowisko programistyczne i narzędzia, które umożliwiają prototypowanie schematów, zapytań i mutacji wdrożonych na serwerze. Automatycznie generuje też pakiety SDK po stronie klienta podczas prototypowania.

Gdy wprowadzisz zmiany w usłudze i aplikacjach klienckich, aktualizacje po stronie serwera i klienta będą gotowe do wdrożenia.

Jak wygląda proces programowania klienta?

Jeśli postępujesz zgodnie z instrukcjami z sekcji Pierwsze kroki, znasz już ogólny proces tworzenia aplikacji na platformę SQL Connect. W tym przewodniku znajdziesz bardziej szczegółowe informacje o generowaniu pakietów Android SDK na podstawie schematu oraz o pracy z zapytaniami i mutacjami klienta.

Podsumowując, aby używać wygenerowanych pakietów Android SDK w aplikacjach klienckich, musisz wykonać te czynności:

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

Następnie:

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

  3. Zainicjuj kod klienta i zaimportuj biblioteki.

  4. Zaimplementuj wywołania zapytań i mutacji.

  5. Skonfiguruj emulator SQL Connect i używaj go, a następnie powtarzaj te czynności.

Wygeneruj pakiet SDK dla języka Kotlin

Użyj interfejsu wiersza poleceń Firebase, aby skonfigurować w aplikacjach pakiety SDK wygenerowane przez SQL Connect. 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 prototypowania

Jeśli masz zainstalowane rozszerzenie SQL Connect VS Code, wygenerowane pakiety SDK będą zawsze aktualne.

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

firebase dataconnect:sdk:generate --watch

Generowanie pakietów SDK w potokach kompilacji

Możesz używać interfejsu wiersza poleceń Firebase do generowania pakietów SDK SQL Connect w procesach kompilacji CI/CD.

firebase dataconnect:sdk:generate

Konfigurowanie kodu klienta

Włączanie SQL Connect do kodu klienta

Aby skonfigurować kod klienta do korzystania z SQL Connect i wygenerowanego pakietu SDK, najpierw postępuj zgodnie ze standardowymi instrukcjami konfiguracji Firebase.

Następnie dodaj do sekcji plugins w pliku app/build.gradle.kts ten kod:

// 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 do sekcji dependencies w pliku app/build.gradle.kts ten kod:

implementation(platform("com.google.firebase:firebase-bom:35.0.1"))
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 SDK SQL Connect

Zainicjuj instancję SQL Connect, używając informacji, które zostały użyte do skonfigurowania SQL Connect. Te informacje znajdziesz na stronie Databases & Storage (Bazy danych i miejsce na dane) > SQL Connect w konsoli Firebase.

Obiekt ConnectorConfig

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

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

Pobieranie instancji oprogramowania sprzęgającego

Po skonfigurowaniu obiektu konfiguracji pobierz 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, jak określono w 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
  }
}

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ć wiele 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ż zbierać dane Flow, które będą 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

Subskrybowanie zmian w czasie rzeczywistym

Zobacz Otrzymywanie aktualizacji w czasie rzeczywistym z SQL Connect.

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 typu wyliczeniowego. Wyobraź sobie na przykład, że na późniejszym etapie cyklu życia aplikacji postanawiasz dodać wartość FULLSCREEN do typu wyliczeniowego AspectRatio.

W przepływie pracy SQL Connect możesz używać lokalnych narzędzi dla programistów do aktualizowania zapytań i pakietów SDK.

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

Przykładowa odporna implementacja

Wygenerowany pakiet SDK wymusza obsługę nieznanych wartości, ponieważ kod klienta musi rozpakować obiekt EnumValue, który jest EnumValue.Known w przypadku znanych wartości typu wyliczeniowego 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łącz buforowanie po stronie klienta

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

Aby włączyć buforowanie po stronie klienta, dodaj konfigurację buforowania 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, które są opcjonalne:

  • maxAge: maksymalny wiek odpowiedzi z pamięci podręcznej, zanim pakiet SDK klienta pobierze nowe wartości. Przykłady: „0”, „30s”, „1h30m”.

    Domyślna wartość parametru maxAge to 0, co oznacza, że odpowiedzi są przechowywane w pamięci podręcznej, ale pakiet SDK klienta zawsze pobiera nowe wartości. Wartości z pamięci podręcznej będą używane tylko wtedy, gdy parametr CACHE_ONLY ma wartość execute().

  • storage: pakiet SDK klienta można skonfigurować tak, aby zapisywał odpowiedzi w pamięci podręcznej w persistent lub memory. Wyniki zapisane w pamięci podręcznej w pamięci persistent będą zachowywane po ponownym uruchomieniu aplikacji. W pakietach Android SDK domyślna wartość to persistent.

Po zaktualizowaniu konfiguracji buforowania oprogramowania sprzęgającego wygeneruj ponownie pakiety SDK klienta i przebuduj 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 konieczności wykonywania dodatkowych czynności. Pamiętaj jednak o tych kwestiach:

  • Domyślne działanie execute() jest opisane powyżej: jeśli wynik zapytania jest przechowywany w pamięci podręcznej, a wartość w pamięci podręcznej nie jest starsza niż maxAge, używana jest wartość z pamięci podręcznej. To działanie domyślne jest nazywane zasadą PREFER_CACHE.

    Możesz też określić, czy poszczególne wywołania execute() mają wyświetlać tylko wartości z pamięci podręcznej (CACHE_ONLY) czy 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)
    

    Prototypowanie i testowanie aplikacji na Androida

    Instrumentowanie klientów pod kątem korzystania z lokalnego emulatora

    Możesz używać emulatora SQL Connect z poziomu rozszerzenia SQL Connect VS Code lub interfejsu wiersza poleceń.

    Instrumentacja aplikacji w celu połączenia z emulatorem jest taka sama 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, zmień w komentarz wiersze dotyczące połączenia z emulatorem.

    Typy SQL w pakietach SDK SQL Connect

    Serwer SQL Connect reprezentuje standardowe i niestandardowe typy danych GraphQL. W pakiecie SDK są one reprezentowane w następujący sposób.

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