Как использовать сгенерированные Android SDK

Клиентские SDK Firebase SQL Connect позволяют вызывать запросы и изменения на стороне сервера непосредственно из приложения Firebase. Вы генерируете собственный клиентский SDK параллельно с разработкой схем, запросов и изменений, которые развертываете в сервисе SQL Connect. Затем вы интегрируете методы из этого SDK в логику клиента.

Как мы уже упоминали, важно отметить, что SQL Connect запросы и изменения не отправляются клиентским кодом и не выполняются на сервере. Вместо этого при развертывании операции SQL Connect хранятся на сервере, как и функции Cloud Functions. Это означает, что вам нужно развернуть соответствующие клиентские изменения, чтобы избежать сбоев у существующих пользователей (например, в старых версиях приложения).

Поэтому SQL Connect предоставляет среду разработки и инструменты, позволяющие создавать прототипы схем, запросов и изменений, развернутых на сервере. Кроме того, он автоматически генерирует клиентские SDK во время создания прототипа.

После того как вы внесете изменения в сервис и клиентские приложения, обновления на стороне сервера и клиента будут готовы к развертыванию.

Как выглядит процесс разработки клиента?

Если вы ознакомились с разделом Начало работы, то уже знаете, как в целом разрабатываются приложения для SQL Connect. В этом руководстве вы найдете более подробную информацию о создании Android SDK на основе схемы и работе с клиентскими запросами и изменениями.

Чтобы использовать сгенерированные Android SDK в клиентских приложениях, выполните следующие действия:

  1. Добавьте Firebase в приложение для Android.
  2. Настройте SQL Connect как зависимость в Gradle.
  3. Добавьте плагин Kotlin Serialization Gradle и зависимость Gradle.

Затем:

  1. Разработайте схему приложения.
  2. Настройте создание SDK:

    • С помощью кнопки Add SDK to app (Добавить SDK в приложение) в расширении SQL Connect для VS Code.
    • Обновите connector.yaml
  3. Инициализируйте клиентский код и импортируйте библиотеки.

  4. Реализуйте вызовы запросов и изменений.

  5. Настройте и используйте эмулятор SQL Connect и повторите.

Сгенерируйте Kotlin SDK

Используйте CLI Firebase, чтобы настроить сгенерированные SDK SQL Connect в своих приложениях. Команда init должна обнаружить все приложения в текущей папке и автоматически установить сгенерированные SDK.

firebase init dataconnect:sdk

Обновление SDK при создании прототипов

Если у вас установлено расширение SQL Connect VS Code, оно будет поддерживать сгенерированные SDK в актуальном состоянии.

Если вы не используете расширение SQL Connect VS Code, то можете поддерживать сгенерированные SDK в актуальном состоянии с помощью интерфейса командной строки Firebase.

firebase dataconnect:sdk:generate --watch

Генерируйте SDK в конвейерах сборки

Вы можете использовать интерфейс командной строки Firebase, чтобы генерировать SDK SQL Connect в процессах сборки CI/CD.

firebase dataconnect:sdk:generate

Настройте код клиента

Добавьте SQL Connect в код клиента

Чтобы настроить клиентский код для использования SQL Connect и сгенерированного SDK, сначала следуйте стандартным инструкциям по настройке Firebase.

Затем добавьте в раздел plugins файла 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

Затем добавьте в раздел dependencies файла app/build.gradle.kts следующий код:

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

Инициализируйте SQL Connect Android SDK

Инициализируйте экземпляр SQL Connect, используя информацию, которую вы указали при настройке SQL Connect. Эту информацию можно найти на странице Databases & Storage (Базы данных и хранилище) > SQL Connect (Подключение SQL) в консоли Firebase.

Объект ConnectorConfig

Для SDK требуется объект конфигурации коннектора.

Этот объект автоматически создается из serviceId и location в dataconnect.yaml, а также connectorId в connector.yaml.

Как получить экземпляр коннектора

После настройки объекта конфигурации получите экземпляр коннектора SQL Connect. Код для коннектора будет сгенерирован эмулятором SQL Connect. Если ваш коннектор называется movies, а пакет Kotlin – com.myapplication, как указано в connector.yaml, то получить объект коннектора можно с помощью следующего вызова:

val connector = com.myapplication.MoviesConnector.instance

Используйте запросы и мутации из Android SDK

С помощью объекта коннектора можно выполнять запросы и изменения, определенные в исходном коде GraphQL. Предположим, что в вашем коннекторе определены следующие операции:

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

то вы можете создать и получить фильм следующим образом:

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

Вы также можете получить несколько фильмов:

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)

Вы также можете собирать данные Flow, которые будут возвращать результат только при получении нового результата запроса с помощью вызова метода execute() запроса.

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

Подписка на изменения в реальном времени

Подробнее о том, как получать обновления от SQL Connect в реальном времени…

Как обрабатывать изменения в полях перечисления

Схема приложения может содержать перечисления, к которым можно обращаться с помощью запросов GraphQL.

По мере изменения дизайна приложения вы можете добавлять новые допустимые значения перечисления. Например, представьте, что позже в жизненном цикле приложения вы решите добавить значение FULLSCREEN в перечисление AspectRatio.

В рабочем процессе SQL Connect вы можете использовать локальные инструменты разработки, чтобы обновлять запросы и SDK.

Однако до выпуска обновленной версии клиентов старые развернутые клиенты могут перестать работать.

Пример устойчивой реализации

Сгенерированный SDK принудительно обрабатывает неизвестные значения, поскольку код клиента должен распаковать объект EnumValue, который является либо EnumValue.Known для известных значений перечисления, либо EnumValue.Unknown для неизвестных значений.

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

Включить клиентское кеширование

В SQL Connect есть необязательная функция клиентского кеширования, которую можно включить, отредактировав файл connector.yaml. Если эта функция включена, сгенерированные клиентские SDK будут локально кешировать ответы на запросы. Это может уменьшить количество запросов к базе данных, которые делает ваше приложение, и позволит зависящим от базы данных частям вашего приложения работать при прерывании доступа к сети.

Чтобы включить клиентское кеширование, добавьте конфигурацию клиентского кеширования в конфигурацию коннектора:

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

В этой конфигурации есть два необязательных параметра:

  • maxAge – максимальный срок хранения кешированного ответа, по истечении которого клиентский SDK запрашивает новые значения. Примеры: "0", "30s", "1h30m".

    Значение по умолчанию для maxAge – 0. Это означает, что ответы кешируются, но клиентский SDK всегда будет получать новые значения. Кешированные значения будут использоваться, только если для CACHE_ONLY задано execute().

  • storage. Клиентский SDK можно настроить так, чтобы он кешировал ответы в хранилище persistent или memory. Результаты, сохраненные в хранилище persistent, не будут удалены при перезапуске приложения. В Android SDK по умолчанию используется persistent.

После обновления конфигурации кеширования коннектора повторно сгенерируйте клиентские SDK и пересоберите приложение. После этого execute() будет кешировать ответы и использовать кешированные значения в соответствии с настроенными правилами. Обычно это происходит автоматически, без каких-либо дополнительных действий с вашей стороны. Однако обратите внимание на следующее:

  • Поведение execute() по умолчанию описано выше: если результат запроса кеширован и кешированное значение не старше maxAge, то используется кешированное значение. Такое поведение по умолчанию называется правилом PREFER_CACHE.

    Вы также можете указать, чтобы отдельные вызовы execute() либо показывали только кешированные значения (CACHE_ONLY), либо безусловно получали новые значения с сервера (SERVER_ONLY).

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

    Создание прототипа и тестирование приложения для Android

    Как настроить клиенты для использования локального эмулятора

    Вы можете использовать эмулятор SQL Connect как из расширения SQL Connect VS Code, так и из CLI.

    В обоих случаях настройка приложения для подключения к эмулятору выполняется одинаково.

    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
    
    

    Чтобы переключиться на рабочие ресурсы, закомментируйте строки для подключения к эмулятору.

    Типы SQL в SDK SQL Connect

    Сервер SQL Connect представляет стандартные и пользовательские типы данных GraphQL. В SDK они представлены следующим образом:

    Тип SQL Connect Kotlin
    Строка Строка
    ПЕР Int (32-битное целое число)
    Число с плавающей запятой Double (64-разрядное число с плавающей запятой)
    Логическое значение Логическое значение
    UUID java.util.UUID
    Дата com.google.firebase.dataconnect.LocalDate (до версии 16.0.0-beta03 – java.util.Date)
    Временная метка com.google.firebase.Timestamp
    Int64 Длинный
    Любые com.google.firebase.dataconnect.AnyValue