Korzystanie z wygenerowanych pakietów Flutter SDK

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

Jak już wspominaliśmy, warto pamiętać, że Data Connect zapytania i mutacje nie są przesyłane przez kod klienta i wykonywane na serwerze. Zamiast tego po wdrożeniu operacje Data 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 Data Connect udostępnia środowisko programistyczne i narzędzia, które umożliwiają tworzenie prototypów schematów, zapytań i mutacji wdrażanych na serwerze. Podczas tworzenia prototypu automatycznie generuje też pakiety SDK po stronie klienta.

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

Jak wygląda proces tworzenia aplikacji klienckiej?

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

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

  1. Dodaj Firebase do aplikacji Flutter.
  2. Zainstaluj interfejs wiersza poleceń flutterfiredart pub global activate flutterfire_cli.
  3. Uruchom flutterfire configure.

Następnie:

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

  3. Zainicjuj kod klienta i zaimportuj biblioteki.

  4. Wdróż wywołania zapytańmutacji.

  5. Skonfiguruj i używaj Data Connect emulatora oraz iteruj.

Generowanie pakietu Flutter SDK

Użyj interfejsu wiersza poleceń Firebase, aby skonfigurować w aplikacjach wygenerowane pakiety SDK Data 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 tworzenia prototypu

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

Jeśli nie używasz rozszerzenia Data 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ć Data Connect pakiety SDK w procesach kompilacji CI/CD.

firebase dataconnect:sdk:generate

Konfigurowanie kodu klienta

Zainicjuj aplikację Data Connect

Najpierw zainicjuj aplikację, korzystając ze standardowych instrukcji konfiguracji Firebase.

Następnie zainstaluj wtyczkę Data Connect:

flutter pub add firebase_data_connect

Zainicjuj Data Connectpakiet SDK Flutter.

Zainicjuj instancję Data Connect, używając informacji, których użyto do skonfigurowania Data Connect (wszystkie są dostępne na karcie Firebase konsoliData Connect).

Importowanie bibliotek

Do zainicjowania kodu klienta potrzebne są 2 zestawy importów: ogólne importyData Connect i konkretne, wygenerowane importy SDK.

// general imports
import 'package:firebase_data_connect/firebase_data_connect.dart';

// generated queries and mutations from SDK
import 'generated/movies.dart';

Używanie zapytań po stronie klienta

Wygenerowany kod będzie już zawierać wstępnie zdefiniowane odwołania do zapytań. Wystarczy zaimportować i wywołać na nich funkcję execute.

import 'generated/movies.dart';

await MoviesConnector.instance.listMovies().execute();

Wywoływanie metod zapytań pakietu SDK

Oto przykład użycia tych funkcji skrótów do działań:

import 'generated/movies.dart';

function onBtnClick() {
  // This will call the generated Dart from the CLI and then make an HTTP request to the server.
  MoviesConnector.instance.listMovies().execute().then(data => showInUI(data)); // == MoviesConnector.instance.listMovies().ref().execute();
}

Pola opcjonalne

Niektóre zapytania mogą mieć pola opcjonalne. W takich przypadkach pakiet Flutter SDK udostępnia metodę budującą, którą należy ustawić osobno.

Na przykład pole rating jest opcjonalne podczas wywoływania funkcji createMovie, więc musisz je podać w funkcji konstruktora.

await MoviesConnector.instance.createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi"}).rating(5).execute();

Subskrybowanie zmian

Możesz zasubskrybować zmiany (które będą aktualizowane za każdym razem, gdy wykonasz zapytanie).

QueryRef<ListMoviesData, void> listRef = MoviesConnector.instance.listMovies().ref();

// subscribe will immediately invoke the query if no execute was called on it previously.
listRef.subscribe().listen((data) {
  updateUIWithMovies(data.movies);
});

await MoviesConnector.instance.createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi" }).rating(5).execute();
await listRef.execute(); // will update the subscription above`

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. Załóżmy na przykład, że w późniejszym okresie cyklu życia aplikacji zdecydujesz się dodać wartość FULLSCREEN do wyliczenia AspectRatio.

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

Zanim jednak udostępnisz zaktualizowaną wersję klientów, starsi wdrożeni klienci mogą przestać działać.

Przykład odpornej implementacji

Wygenerowany pakiet SDK wymusza obsługę nieznanych wartości. Oznacza to, że kod klienta musi rozpakować obiekt EnumValue do obiektu Known lub Unknown.

final result = await MoviesConnector.instance.listMovies().execute();

if (result.data != null && result.data!.isNotEmpty) {
  handleEnumValue(result.data![0].aspectratio);
}

void handleEnumValue(EnumValue<AspectRatio> aspectValue) {
  if (aspectValue.value != null) {
    switch(aspectValue.value!) {
      case AspectRatio.ACADEMY:
        print("This movie is in Academy aspect");
        break;
      case AspectRatio.WIDESCREEN:
        print("This movie is in Widescreen aspect");
        break;
      case AspectRatio.ANAMORPHIC:
        print("This movie is in Anamorphic aspect");
        break;
      case AspectRatio.IMAX:
        print("This movie is in IMAX aspect");
    }
  } else {
    print("Unknown aspect ratio detected: ${aspectValue.stringValue}");
  }
}

Włączanie zapisywania w pamięci podręcznej po stronie klienta

Data 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 do klienta lokalnie buforują odpowiedzi na zapytania, co może zmniejszyć liczbę żądań bazy danych wysyłanych przez aplikację i umożliwić działanie części aplikacji zależnych od bazy danych w przypadku przerw w dostępie do sieci.

Aby włączyć buforowanie po stronie klienta, dodaj konfigurację buforowania po stronie klienta do konfiguracji łącznika:

generate:
  javascriptSdk:
    outputDir: ../dart/
    package: "dataconnect_generated"
    clientCache:
      maxAge: 5s
      storage: memory

Ta konfiguracja ma 2 parametry, które są opcjonalne:

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

    Domyślna wartość parametru maxAge to 0, co oznacza, że odpowiedzi są buforowane, 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(), a początkowy wynik został zwrócony przez subscribe().

  • storage: Pakiet SDK klienta można skonfigurować tak, aby buforował odpowiedzi w pamięci persistent lub w memory. Wyniki zapisane w pamięci podręcznej persistent będą dostępne po ponownym uruchomieniu aplikacji. W przypadku kierowania reklam na Androida lub iOS domyślna wartość to persistent. W przypadku kierowania na przeglądarki obsługiwana jest tylko pamięć memory.

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

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

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

    await queryRef.execute(fetchPolicy: QueryFetchPolicy.cacheOnly);
    
    await queryRef.execute(fetchPolicy: QueryFetchPolicy.serverOnly);
    
  • Gdy wywołasz funkcję subscribe(), zawsze natychmiast zwróci ona buforowaną treść, jeśli istnieje, niezależnie od ustawienia maxAge. Kolejne wywołania funkcji execute() będą powiadamiać słuchaczy zgodnie ze skonfigurowanym maxAge.

Używanie mutacji po stronie klienta

Mutacje są dostępne w taki sam sposób jak zapytania.

await MoviesConnector.instance.createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi" }).rating(5).execute();

Tworzenie prototypów i testowanie aplikacji we Flutterze

Instrumentowanie klientów do korzystania z lokalnego emulatora

Możesz użyć Data Connect emulatora, korzystając z rozszerzenia Data Connect VS Code lub interfejsu CLI.

Instrumentowanie aplikacji w celu połączenia z emulatorem jest takie samo w obu scenariuszach.

import 'package:firebase_data_connect/firebase_data_connect.dart';
import 'generated/movies.dart';

MoviesConnector.instance.dataConnect
          .useDataConnectEmulator('127.0.0.1', 9399);

// Make calls from your app
QueryRef<ListMoviesData, void> ref = MoviesConnector.instance.listMovies.ref();

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

Typy danych w pakiecie Dart SDK

Data Connect serwer reprezentuje typowe typy danych GraphQL. W pakiecie SDK są one reprezentowane w ten sposób:

Data Connect Typ Dart
Sygnatura czasowa firebase_data_connect.Timestamp
Liczba całkowita (32-bitowa) int
Data DateTime
UUID ciąg znaków
Int64 int
Liczba zmiennoprzecinkowa podwójny
Wartość logiczna bool
Dowolna firebase_data_connect.AnyValue