Usar SDKs do Android gerados

Com os SDKs do cliente do Firebase SQL Connect, é possível chamar consultas e mutações do lado do servidor diretamente de um app do Firebase. Você gera um SDK do cliente personalizado em paralelo ao projetar os esquemas, as consultas e as mutações que implanta no serviço do SQL Connect. Em seguida, integre os métodos desse SDK à lógica do cliente.

Como já mencionamos, é importante observar que as consultas e mutações do SQL Connect não são enviadas pelo código do cliente e executadas no servidor. Em vez disso, quando implantadas, as operações SQL Connect são armazenadas no servidor, como o Cloud Functions. Isso significa que você precisa implantar as mudanças correspondentes no lado do cliente para evitar problemas para os usuários atuais (por exemplo, em versões mais antigas do app).

Por isso, o SQL Connect oferece um ambiente de desenvolvimento e ferramentas que permitem prototipar seus esquemas, consultas e mutações implantados no servidor. Ele também gera SDKs do lado do cliente automaticamente durante a prototipagem.

Depois de iterar as atualizações nos apps de serviço e cliente, as atualizações do lado do servidor e do cliente estarão prontas para implantação.

Qual é o fluxo de trabalho de desenvolvimento do cliente?

Se você seguiu as instruções em Primeiros passos, já conhece o fluxo geral de desenvolvimento do SQL Connect. Neste guia, você vai encontrar informações mais detalhadas sobre como gerar SDKs do Android com base no seu esquema e como trabalhar com consultas e mutações de clientes.

Em resumo, para usar SDKs do Android gerados nos seus apps clientes, siga estas etapas de pré-requisito:

  1. Adicione o Firebase ao seu app Android.
  2. Configure SQL Connect como uma dependência no Gradle.
  3. Adicione o plug-in do Gradle de serialização do Kotlin e a dependência do Gradle.

Depois, siga estas instruções:

  1. Desenvolva o esquema do app.
  2. Configure a geração do SDK:

  3. Inicialize o código do cliente e importe as bibliotecas.

  4. Implementar chamadas para consultas e mutações.

  5. Configure e use o emulador do SQL Connect e faça iterações.

Gerar o SDK do Kotlin

Use a CLI Firebase para configurar os SDKs gerados pelo SQL Connect nos seus apps. O comando init detecta todos os apps na pasta atual e instala os SDKs gerados automaticamente.

firebase init dataconnect:sdk

Atualizar SDKs durante a prototipagem

Se você tiver a extensão do VS Code do SQL Connect instalada, ela sempre vai manter os SDKs gerados atualizados.

Se você não usa a extensão do VS Code do SQL Connect, use a CLI do Firebase para manter os SDKs gerados atualizados.

firebase dataconnect:sdk:generate --watch

Gerar SDKs em pipelines de build

Use a CLI do Firebase para gerar SDKs do SQL Connect em processos de build de CI/CD.

firebase dataconnect:sdk:generate

Configurar o código do cliente

Incorporar SQL Connect ao código do cliente

Para configurar o código do cliente para usar o SQL Connect e o SDK gerado, primeiro siga as instruções de configuração padrão do Firebase.

Em seguida, adicione o seguinte à seção plugins em 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

Em seguida, adicione o seguinte à seção dependencies em 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

Inicializar o SDK do Android do SQL Connect

Inicialize a instância SQL Connect usando as informações que você usou para configurar SQL Connect. Encontre essas informações na página Bancos de dados e armazenamento > SQL Connect do console do Firebase.

O objeto ConnectorConfig

O SDK requer um objeto de configuração do conector.

Esse objeto é gerado automaticamente de serviceId e location em dataconnect.yaml e connectorId em connector.yaml.

Como acessar uma instância de conector

Agora que você configurou um objeto de configuração, receba uma instância do conector SQL Connect. O código do conector será gerado pelo emulador do SQL Connect. Se o nome do conector for movies e o pacote Kotlin for com.myapplication, conforme especificado em connector.yaml, recupere o objeto do conector chamando:

val connector = com.myapplication.MoviesConnector.instance

Usar consultas e mutações do SDK do Android

Com o objeto do conector, é possível executar consultas e mutações conforme definido no código-fonte do GraphQL. Suponha que o conector tenha estas operações definidas:

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

você pode criar e recuperar um filme da seguinte maneira:

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

Também é possível recuperar vários filmes:

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)

Também é possível coletar um Flow que só vai produzir um resultado quando um novo resultado de consulta for recuperado usando uma chamada para o método execute() da consulta.

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

Receber notificações sobre mudanças em tempo real

Consulte Receber atualizações em tempo real do SQL Connect.

Processar mudanças em campos de enumeração

O esquema de um app pode conter enumerações, que podem ser acessadas pelas consultas do GraphQL.

À medida que o design de um app muda, é possível adicionar novos valores compatíveis com o tipo enumerado. Por exemplo, imagine que, mais adiante no ciclo de vida do aplicativo, você decida adicionar um valor FULLSCREEN ao tipo enumerado AspectRatio.

No fluxo de trabalho SQL Connect, é possível usar ferramentas para desenvolvedores locais para atualizar as consultas e os SDKs.

No entanto, antes de lançar uma versão atualizada dos clientes, os clientes implantados mais antigos podem falhar.

Exemplo de implementação resiliente

O SDK gerado força o processamento de valores desconhecidos, já que o código do cliente precisa desencapsular o objeto EnumValue, que é EnumValue.Known para valores de tipo enumerado conhecidos ou EnumValue.Unknown para valores desconhecidos.

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

Ativar o armazenamento em cache do lado do cliente

O SQL Connect tem um recurso opcional de armazenamento em cache do lado do cliente, que pode ser ativado editando o arquivo connector.yaml. Quando esse recurso está ativado, os SDKs de cliente gerados armazenam em cache localmente as respostas de consulta, o que pode reduzir o número de solicitações de banco de dados que seu app faz e permite que as partes do app que dependem do banco de dados funcionem quando a disponibilidade da rede é interrompida.

Para ativar o armazenamento em cache do lado do cliente, adicione uma configuração de armazenamento em cache do cliente à configuração do conector:

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

Essa configuração tem dois parâmetros, ambos opcionais:

  • maxAge: a idade máxima que uma resposta em cache pode ter antes que o SDK do cliente busque novos valores. Exemplos: "0", "30s", "1h30m".

    O valor padrão de maxAge é 0, o que significa que as respostas são armazenadas em cache, mas o SDK do cliente sempre busca valores novos. Os valores armazenados em cache só serão usados quando CACHE_ONLY for especificado como execute().

  • storage: o SDK do cliente pode ser configurado para armazenar respostas em cache no armazenamento persistent ou em memory. Os resultados armazenados em cache no armazenamento persistent vão persistir nas reinicializações do app. Nos SDKs do Android, o padrão é persistent.

Depois de atualizar a configuração de armazenamento em cache do conector, gere novamente os SDKs do cliente e recrie o app. Depois disso, o execute() vai armazenar em cache as respostas e usar os valores armazenados em cache de acordo com a política que você configurou. Isso geralmente acontece de forma automática, sem que você precise fazer nada. No entanto, observe o seguinte:

  • O comportamento padrão de execute() é o descrito acima: se um resultado for armazenado em cache para uma consulta e o valor armazenado em cache não for mais antigo que maxAge, use o valor armazenado em cache. Esse comportamento padrão é chamado de política PREFER_CACHE.

    Também é possível especificar para invocações individuais de execute() que apenas valores em cache sejam disponibilizados (CACHE_ONLY) ou que valores novos sejam buscados incondicionalmente no servidor (SERVER_ONLY).

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

    Criar protótipos e testar seu app Android

    Instrumentar clientes para usar um emulador local

    É possível usar o emulador SQL Connect, seja na extensão do VS Code do SQL Connect ou na CLI.

    A instrumentação do app para se conectar ao emulador é a mesma nos dois cenários.

    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
    
    

    Para mudar para os recursos de produção, comente as linhas de conexão com o emulador.

    Tipos de SQL em SDKs do SQL Connect

    O servidor SQL Connect representa tipos de dados comuns e personalizados do GraphQL. Eles são representados no SDK da seguinte maneira.

    Tipo SQL Connect Kotlin
    String String
    Int Int (número inteiro de 32 bits)
    Ponto flutuante Double (ponto flutuante de 64 bits)
    Booleano Booleano
    UUID java.util.UUID
    Data com.google.firebase.dataconnect.LocalDate (era java.util.Date até a versão 16.0.0-beta03)
    Carimbo de data/hora com.google.firebase.Timestamp
    Int64 Longo
    Qualquer com.google.firebase.dataconnect.AnyValue