Skip to main content

Implantar armazenamento offline seguro com o SmartStore

Objetivos de aprendizagem

Após concluir esta unidade, você estará apto a:

  • Entender termos e conceitos básicos do SmartStore.
  • Usar o SmartStore para emitir consultas SELECT.
  • Registrar, preencher e gerenciar dados do SmartStore na sua plataforma de destino preferida (iOS, Android, híbrida, React Native).
  • Usar o SmartStore Inspector.

Como usar o SmartStore para armazenamento offline

Os dispositivos móveis podem perder a conexão a qualquer hora, e ambientes como hospitais e aviões costumam proibir a conexão. Para lidar com essas situações, é importante que seus aplicativos móveis continuem a funcionar mesmo quando ficam offline. 

O Mobile SDK oferece o SmartStore, uma solução segura e multifacetada, com vários threads, para armazenamento offline em dispositivos móveis. Com o SmartStore, seus clientes podem continuar a trabalhar com dados em um ambiente seguro, mesmo quando o dispositivo perde a conexão. Ao combinar o SmartStore com a Sincronização móvel, você pode manter os dados locais do SmartStore sincronizados com o servidor do Salesforce facilmente quando a conectividade voltar.

O SmartStore armazena dados como documentos JSON em um banco de dados simples de tabela única. Você pode recuperar dados do SmartStore com métodos auxiliares do Mobile SDK ou com consultas personalizadas usando a linguagem Smart SQL do SmartStore.

Soups

O SmartStore armazena dados offline em conjuntos lógicos chamados soups. O soup do SmartStore representa uma única tabela no banco de dados SQLite subjacente, ou repositório, e normalmente mapeia para um objeto do Salesforce personalizado ou padronizado. Os soups contêm elementos de soup. Cada elemento é um objeto JSON que espelha uma única linha do banco de dados. Para simplificar o acesso a dados, defina índices para cada soup. Os índices são usados para consultar o soup com métodos auxiliares do SmartStore ou com a linguagem de consulta Smart SQL do SmartStore. Os índices do SmartStore também facilitam a sua vida com suporte a consultas de pesquisa de texto completo.

Pense em soups como tabelas e em repositórios como bancos de dados. Você pode definir quantos soups quiser em um aplicativo. Como conjuntos de dados autocontidos, os soups não têm relacionamentos predefinidos uns com os outros, mas você pode usar associações Smart SQL para fazer consultas entre eles. Além disso, nos aplicativos nativos, você pode gravar em vários soups em uma mesma transação.

Nota

Os dados do SmartStore são voláteis. Na maioria dos casos, seu ciclo de vida está vinculado ao usuário autenticado e aos estados do token OAuth. Quando o usuário faz logout do aplicativo, o SmartStore exclui todos os dados de soup associados a esse usuário. Da mesma forma, quando o token de atualização OAuth é revogado ou expira, o estado do aplicativo do usuário é redefinido e todos os dados no SmartStore são limpos. Ao projetar seu aplicativo, pense na volatilidade dos dados do SmartStore, especialmente se sua organização define um ciclo de vida curto para o token de atualização.

Smart SQL

O SmartStore é compatível com a linguagem de consulta Smart SQL para instruções SELECT de forma livre. Apenas as instruções SELECT têm suporte. O Smart SQL combina toda a gramática SELECT SQL padrão com sintaxe especial para referenciar soups e campos de soups. Essa abordagem permite o máximo de controle e flexibilidade, incluindo a capacidade de usar combinações.

Sintaxe

A sintaxe é idêntica à especificação SELECT SQL padrão, mas com as seguintes adaptações:

Uso Sintaxe
Para especificar uma coluna {<soupName>:<path>}
Para especificar uma tabela {<soupName>}
Para referenciar toda uma sequência de caracteres JSON de entrada de soup {<soupName>:_soup}
Para referenciar toda uma ID de entrada de soup interna {<soupName>:_soupEntryId}
Para fazer referenciar a última data de modificação {<soupName>:_soupLastModifiedDate}

Consultas de exemplo

Imagine dois soups: um chamado Funcionários e outro chamado Departamentos. O soup Funcionários contém campos padrão como:

  • Nome (firstName)
  • Sobrenome (lastName)
  • Código do departamento (deptCode)
  • ID do funcionário (employeeId)
  • ID de gerente (managerId)

O soup Departamentos contém:

  • Nome (name)
  • Código do departamento (deptCode)

Vejamos alguns exemplos de consultas Smart SQL básicas que usam esses soups:

select {employees:firstName}, {employees:lastName} 
 from {employees} order by {employees:lastName}
select {departments:name} 
 from {departments} 
 order by {departments:deptCode}

Combinações

O Smart SQL também permite o uso de combinações. Por exemplo:

select {departments:name}, {employees:firstName} || ' ' || {employees:lastName}  
 from {employees}, {departments}  
 where {departments:deptCode} = {employees:deptCode}  
 order by {departments:name}, {employees:lastName}

Você pode fazer até autocombinações:

select mgr.{employees:lastName}, e.{employees:lastName}  
 from {employees} as mgr, {employees} as e  
 where mgr.{employees:employeeId} = e.{employees:managerId}
Nota

uma combinação em um índice JSON1 exige uma sintaxe levemente estendida. Por exemplo, em vez de

select {soup1:path1} from {soup1}, {soup2}

use

select {soup1}.{soup1:path1} from {soup1}, {soup2}

Funções agregadas

O Smart SQL é compatível com o uso de funções agregadas, como:

  • COUNT
  • SUM
  • AVG

Por exemplo:

select {account:name}, 
    count({opportunity:name}),
    sum({opportunity:amount}),
    avg({opportunity:amount}),
    {account:id},
    {opportunity:accountid} 
 from {account},
    {opportunity} 
 where {account:id} = {opportunity:accountid} 
 group by {account:name}

Como registrar um soup

Antes de usar um soup, registre-o. Se o soup não existir, o registro o criará. Se ele existir, o registro dará acesso a ele. Para registrar soups, você cria um arquivo de configuração JSON e carrega-o no tempo de execução. Um único arquivo de configuração pode definir todos os soups do seu aplicativo. O Mobile SDK dá suporte a arquivos de configuração em aplicativos nativos e híbridos.

Os arquivos de configuração registram soups no repositório de usuário padrão ou no repositório global padrão. Para usar outros repositórios nomeados ou externos, você precisa registrar soups com APIs do SmartStore. O Mobile SDK fornece métodos para definir o nome e os índices de um soup para depois registrá-lo.

Ao registrar um soup, você cria uma estrutura nomeada vazia na memória que fica aguardando dados. Normalmente, o soup é inicializado com dados de uma organização do Salesforce. Para obter dados do Salesforce, use o mecanismo de solicitação REST padrão do Mobile SDK. Quando uma resposta REST bem-sucedida chegar, extraia os dados do objeto de resposta e insira-os e atualize-os em seu soup:

Durante a criação do soup, os erros podem ocorrer por vários motivos, inclusive:

  • Um nome de soup inválido
  • Falta de índice (pelo menos um índice tem de ser especificado)
  • Outros erros imprevistos, como um erro de banco de dados

Estrutura do soup

Para definir um soup, forneça um nome para ele e uma lista de uma ou mais especificações de índice. Os índices são baseados em campos do soup. Você não precisa fornecer uma especificação de índice para cada campo armazenado no soup. Por exemplo, se você está usando o soup como um repositório chave-valor simples, use uma única especificação de índice do tipo string. Quando os soups são criados, o SmartStore usa os índices para rastrear as operações de inserção, atualização ou exclusão.

O SmartStore dá suporte aos tipos de dados de índice a seguir.

  • string (sequência de caracteres)
  • integer (número inteiro)
  • floating (flutuante)
  • full_text (texto_completo)
  • json1

Como definir índices

Nos aplicativos nativos e híbridos, você pode usar arquivos de configuração para registrar soups e definir seus índices. Em aplicativos React Native, você usa código JavaScript. Algumas regras se aplicam em cada caso.

  • Os caminhos de índice diferenciam maiúsculas de minúsculas e podem incluir caminhos compostos, como Owner.Name.
  • As entradas de índice em que faltem campos descritos em uma matriz de especificação de índice não são rastreadas nesse índice.
  • O tipo do índice se aplica somente ao índice. Ao consultar um campo indexado (por exemplo, “select {soup:path} from {soup}”), a consulta retorna dados no tipo definido na especificação de índice.
  • As colunas de índice podem conter campos nulos.
  • A partir do Mobile SDK 9.1, os caminhos de índice não são mais obrigatórios para campos referenciados nas cláusulas SELECT ou WHERE.
  • Você pode especificar caminhos de índice que apontem para nós internos (fora da folha). Você pode usar caminhos internos com consultas like e match (texto completo). Use o tipo sequência de caracteres quando definir caminhos internos de nó. Por exemplo, considere este elemento em um soup chamado "espiões":
    {  
       "first_name":"James",
       "last_name":"Bond",
       "address":{  
          "street_number":10,
          "street_name":"downing",
          "city":"london"
       }
     }
    Neste caso, “address” é um nó interno porque tem filhos. Pelo índice no caminho “address”, você pode usar uma consulta like ou match para encontrar o valor “city” (london) em “address”. Por exemplo:
    SELECT {spies:first_name, spies:last_name} FROM spies WHERE {spies:address} LIKE 'london'

Formato do arquivo de configuração

Eis um exemplo hipotético de um arquivo de configuração JSON que define dois soups, soup1 e soup2 e demonstra toda a gama de tipos de dados de índice.

{  "soups": [
    {
      "soupName": "soup1",
      "indexes": [
        { "path": "stringField1", "type": "string"},
        { "path": "integerField1", "type": "integer"},
        { "path": "floatingField1", "type": "floating"},
        { "path": "json1Field1", "type": "json1"},
        { "path": "ftsField1", "type": "full_text"}
      ]
    },
    {
      "soupName": "soup2",
      "indexes": [
        { "path": "stringField2", "type": "string"},
        { "path": "integerField2", "type": "integer"},
        { "path": "floatingField2", "type": "floating"},
        { "path": "json1Field2", "type": "json1"},
        { "path": "ftsField2", "type": "full_text"}
      ]
    }
  ]
 }

Para obter mais informações sobre o registro de seus soups com código em vez de arquivos de configuração, consulte o Guia de desenvolvimento do Salesforce Mobile SDK.

Nota

Se seu código e seu arquivo de configuração registrarem um soup com o mesmo nome, o Mobile SDK ignorará a definição no arquivo de configuração.

O arquivo de configuração a seguir registra um único soup com base nos registros de conta. Esse soup indexa os campos nome, ID e ID de proprietário (ou pai). Os nomes de soup não precisam corresponder ao nome de um objeto Salesforce de origem, mas uma referência óbvia costuma ser uma boa escolha.

{  "soups": [
    {
      "soupName": "account",
      "indexes": [
        { "path": "Name", "type": "string"},
        { "path": "Id", "type": "string"},
        { "path": "OwnerId", "type": "string"}
      ]
    }
  ]
 }

Como inserir ou atualizar entradas de soup

Para inserir ou atualizar entradas de soup, deixando que o SmartStore determine a ação apropriada, use um método upsert. Por exemplo, um aplicativo híbrido pode usar uma destas versões de JavaScript:

navigator.smartStore.upsertSoupEntries(isGlobalStore, soupName, 
    entries[], successCallback, errorCallback)
navigator.smartStore.upsertSoupEntries(storeConfig, soupName, 
    entries[], successCallback, errorCallback)

Forneça o nome do soup, uma matriz de entradas formatadas como sequência de caracteres JSON e funções opcionais de retorno de chamada de sucesso e de erro. A única diferença entre os dois métodos é o primeiro parâmetro. Se seu soup reside em um repositório global ou de usuário nomeado, use o parâmetro storeConfig para fornecer o tipo de repositório e seu nome. Por exemplo:

{isGlobalStore:true, name:"AcmeSales"}

Se você está usando o repositório global ou de usuário padrão, pode simplesmente transmitir true para indicar um repositório global. Do contrário, você pode omitir o argumento. Esse parâmetro é opcional e seu padrão é false. Ele não está presente em métodos nativos, que leem a mesma informação dos objetos relacionados.

Como fazer consultas e gerenciar o SmartStore

O Mobile SDK para aplicativos iOS nativos oferece métodos de fábrica que criam objetos de “especificação de consulta” com base nas suas informações. Os métodos de fábrica criam consultas com base nos seguintes operadores WHERE:

  • = (operador "exact")
  • LIKE
  • MATCH (extensão de pesquisa em texto inteiro)
  • BETWEEN, <=, >= (consultas a intervalos)
  • ALL

Esses objetos de consulta lidam com consultas simples e diretas e poupam você do trabalho de codificá-las por conta própria. Para aumentar as nuances em situações mais complexas, você pode codificar sua própria consulta Smart SQL e transmiti-la para o método de fábrica Smart SQL. Depois de obter um objeto de consulta, transmita-o a um método de execução para recuperar os dados de soup especificados.

Como gerenciar um soup

Às vezes você quer limpar dados não usados ou melhorar o desempenho de um soup alterando seus índices. Para essas tarefas, o SmartStore oferece um conjunto de métodos que realizam tarefas de diagnóstico, manutenção e gerenciamento. Use esses métodos para obter informações sobre um soup ou sobre um repositório, editar a estrutura de um soup ou excluir soups e repositórios.

Mais especificamente, com esses métodos você pode:

  • Obter o tamanho do banco de dados subjacente
  • Obter uma lista de todos os repositórios (usuário ou global)
  • Verificar se existe um soup com o nome indicado
  • Recuperar a especificação de um soup e suas especificações de índice
  • Alterar a configuração de um soup
  • Reindexar um soup
  • Limpar todos os registros de um soup
  • Remover um soup do repositório
  • Remover um repositório
  • Remover todos os repositórios (usuário ou global)

Esses métodos estão disponíveis em todas as plataformas para todos os tipos de aplicativo.

Como usar o SmartStore Inspector

Durante os testes, é útil ver se seu código está tratando os dados do SmartStore da forma pretendida. O SmartStore Inspector oferece uma ferramenta de IU para esse fim. Com ele, você pode:

  • Examinar metadados de soup, como nomes de soup e especificações de índice para qualquer soup
  • Limpar o conteúdo de um soup
  • Executar consultas Smart SQL

Para um acesso mais fácil, inicie o SmartStore Inspector na caixa de diálogo Dev Support. 

Como você acessa o menu Dev Support depende do seu ambiente de desenvolvimento. Para iniciar a caixa de diálogo, use uma das opções a seguir.

Android

Executar uma das seguintes opções:

  • Quando seu aplicativo está em execução no emulador Android, use o atalho do teclado Command+m (Mac) ou Ctrl+m (Windows).
  • Em um shell de comando do sistema, execute: adb shell input keyevent 82

iOS

  • Em um dispositivo físico, use o gesto de sacudir para fazer o menu Dev Support aparecer e escolha SmartStore Inspector.
  • No simulador de iOS, selecione o item de menu Hardware > Gesto de sacudir ou use o atalho de teclado ^+Command+z.

Como usar o SmartStore em aplicativos iOS nativos

A adição do módulo SmartStore a novos aplicativos iOS nativos não exige esforço a mais. Qualquer aplicativo forceios nativo criado inclui automaticamente a biblioteca SmartStore.

Como registrar soups com um arquivo de configuração

Em aplicativos iOS nativos, o Mobile SDK procura arquivos de configuração em / (nível mais alto) no bundle Recursos.

  1. Adicione arquivos de configuração ao seu projeto.
    1. No navegador do projeto Xcode, selecione o nó do projeto.
    2. Na janela do editor, selecione Build Phases (Criar etapas).
    3. Expanda Copy Bundle Resources (Copiar recursos do pacote).
    4. Clique em + (”Adicionar itens”).
    5. Selecione seu arquivo de configuração do soup. Se seu arquivo já não estiver em uma pasta do projeto Xcode:
      1. Para selecionar seu arquivo no Finder, clique em Add Other... (Adicionar outro...).
      2. Quando for solicitada a criação de grupos, clique em Finish (Concluir).
  2. Adicione uma única linha de código para cada arquivo fornecido.
    • Para carregar um arquivo userstore.json, use um dos seguintes:
      SmartStoreSDKManager.shared().setupUserStoreFromDefaultConfig()
    • Para carregar um arquivo globalstore.json, use um dos seguintes:
      SalesforceManager.shared().setupGlobalStoreFromDefaultConfig()

Como preencher um soup

Ao registrar um soup, você cria uma estrutura nomeada vazia na memória que fica aguardando dados. Para preencher o soup com dados do Salesforce, use o mecanismo de solicitação REST padrão para obter os dados. Quando uma resposta REST bem-sucedida chegar, extraia os dados do objeto de resposta e insira-os e atualize-os em seu soup. Para obter detalhes de código, consulte o exemplo ao final desta seção de iOS.

Como consultar dados do soup

No iOS, você cria objetos de especificação de consulta chamando métodos de classe na classe SFQuerySpec. Por exemplo, em Objective-C, o método newSmartQuerySpec:withPageSize: retorna um objeto SFQuerySpec que encapsula determinada sequência de caracteres de consulta Smart SQL:

var querySpec = store.buildSmartQuerySpec(
    smartSql: "select {account:Name} from {account}",
    pageSize: 10)

O parâmetro de tamanho de página determina quantos registros são enviados em cada página de resultados. Esses métodos dão maior flexibilidade do que outras funções de fábrica de consulta porque você fornece sua própria instrução SELECT Smart SQL. Por exemplo, o código a seguir emite uma consulta que chama a função SQL COUNT. Como COUNT retorna um único valor, o único tamanho de página possível é um.

O código a seguir emite uma consulta que chama a função SQL COUNT. Como COUNT retorna um único valor, o único tamanho de página possível é um.

Para executar uma consulta, transmita o seu objeto SFQuerySpec para o método query() no objeto SFSmartStore.

var querySpec = store.buildSmartQuerySpec(
    smartSql: "select count(*) from {employees}",
    pageSize: 1)

Como gerenciar um soup

Para usar APIs Objective-C de gerenciamento de soup em um aplicativo iOS nativo, importe SmartStore/SFSmartStore.h. Chame métodos de gerenciamento de soup em uma instância compartilhada de SFSmartStore. Obtenha a instância compartilhada usando um dos métodos de classe SFSmartStore a seguir.

Para obter a instância do SmartStore para o usuário atual:

var store = SmartStore.shared(withName:storeName)

Para obter a instância do SmartStore para um usuário específico:

var store = SmartStore.shared(withName:storeName, forUserAccount:user)

Por exemplo, para chamar o método de gerenciamento removeSoup::

self.store = [SFSmartStore sharedStoreWithName:kDefaultSmartStoreName];
 if ([self.store soupExists:@"Accounts"]) {
    [self.store removeSoup:@"Accounts"];
 }

Exemplo

Neste exemplo, você cria um aplicativo Swift. O modelo Swift nativo para forceios já inclui uma implementação SmartStore, ou seja, vamos apenas rever sua configuração. 

  1. Com o forceios, crie um projeto Swift nativo semelhante ao exemplo a seguir:
    $ forceios create Enter your application type (native_swift or native, leave empty for native_swift):<Press RETURN>
    Enter your application name:<Enter any name you like>
    Enter your package name:com.myapps.ios
    Enter your organization name (Acme, Inc.):MyApps.com
    Enter output directory for your app (leave empty for the current directory):<Press RETURN or enter a directory name>
  2. Abra o arquivo .xcworkspace do seu aplicativo no Xcode.
  3. Na pasta do projeto, expanda Arquivos de suporte.
  4. Abra o arquivo userstore.json e inspecione a configuração do SmartStore.
  5. Para adicionar o arquivo de configuração ao pacote do aplicativo compilado, o modelo faz referência a esses arquivos em Configurações do projeto.
    1. No navegador do projeto Xcode, selecione o nó principal do projeto.
    2. Na janela do editor, selecione Build Phases (Criar etapas).
    3. Expanda Copy Bundle Resources (Copiar recursos do pacote).
    4. Observe que userstore.json está incluído na lista.
  6. Em sua pasta de código-fonte do projeto, selecione Classes/SceneDelegate.swift.
  7. No método scene(_:willConnectTo:options:), encontre a chamada para setupRootViewController().
  8. Para ver onde os arquivos de configuração do SmartStore estão carregados, clique Ctrl + setupRootViewController() e selecione Pular para a definição.

Para visualizar a configuração do SmartStore do aplicativo no tempo de execução: 

  1. Inicie o aplicativo.
  2. Depois de fazer login com sucesso e autorizar o aplicativo, abra o menu Dev Tools.
    1. Digite control + command + z se estiver usando o emulador de iOS, ou sacuda seu dispositivo iOS.
    2. Clique em Inspecionar SmartStore.
    3. Para listar os soups e a quantidade de registros, clique em Soups.

Como usar o SmartStore em aplicativos Android nativos

Por padrão, todos os aplicativos forcedroid e forceios nativos incluem bibliotecas do SmartStore e da Sincronização móvel. No entanto, os aplicativos Android mais antigos podem exigir algumas etapas de configuração personalizada.

  1. Em seu projeto Android nativo, abra MainApplication.java.
  2. Adicione a seguinte instrução de importação, caso não esteja presente:
    import com.salesforce.androidsdk.mobilesync.app.MobileSyncSDKManager;
  3. Encontre a linha que chama initNative(). Por exemplo:
    SalesforceSDKManager.initNative(getApplicationContext(), new NativeKeyImpl(), MainActivity.class);
  4. Se initNative() é chamada no SalesforceSDKManager, altere SalesforceSDKManager para MobileSyncSDKManager:
    MobileSyncSDKManager.initNative(getApplicationContext(), new NativeKeyImpl(), MainActivity.class);

Como registrar soups com um arquivo de configuração

  1. Coloque seus arquivos de configuração de soup na pasta do projeto /res/raw/.
  2. Adicione uma única linha de código para cada arquivo fornecido.
    • Para carregar um arquivo userstore.json, use
      SmartStoreSDKManager.getInstance().setupUserStoreFromDefaultConfig();
    • Para carregar um arquivo globalstore.json, use
      SmartStoreSDKManager.getInstance().setupGlobalStoreFromDefaultConfig();

Como preencher um soup

Ao registrar um soup, você cria uma estrutura nomeada vazia na memória que fica aguardando dados. Para preencher o soup com dados do Salesforce, use o mecanismo de solicitação REST padrão para obter os dados. Quando uma resposta REST bem-sucedida chegar, extraia os dados do objeto de resposta e insira-os e atualize-os em seu soup:

public void populateAccounts() throws UnsupportedEncodingException {
    final RestRequest restRequest =
        RestRequest.getRequestForQuery(
            ApiVersionStrings.getVersionNumber(SalesforceSDKManager.getInstance().getAppContext()), 
            "SELECT Name, Id, OwnerId FROM Account");
    client.sendAsync(restRequest, new RestClient.AsyncRequestCallback() {
        @Override
        public void onSuccess(RestRequest request, RestResponse result) {
            result.consumeQuietly(); // always call before switching to main thread (unlike here)
            try {
                JSONArray records = result.asJSONObject().getJSONArray("records");
                insertAccounts(records);
            } catch (Exception e) {
                onError(e);
            } finally {
                Log.println(Log.INFO, "REST Success!", "\nSmartStore insertion successful");
            }
        }
        @Override
        public void onError(Exception e)
        {
            Log.e(TAG, e.getLocalizedMessage());
        }
    });
 }
/**
 * Inserts accounts into the accounts soup.
 *
 * @param accounts Accounts.
 */
 public void insertAccounts(JSONArray accounts)
 {
    try {
        if (accounts != null) {
            for (int i = 0; i < accounts.length(); i++) {
                if (accounts.get(i) != null) {
                    try {
                        smartStore.upsert("Accounts", accounts.getJSONObject(i));
                    }
                    catch (JSONException exc) {
                        Log.e(TAG, "Error occurred while attempting to insert account. "
                                +  "Please verify validity of JSON data set.");
                    }
                }
            }
        }
    }
    catch (JSONException e) {
        Log.e(TAG, "Error occurred while attempting to insert accounts. "
                + "Please verify validity of JSON data set.");
    }
 }

Como consultar dados de soup com o Smart SQL

No Android, você cria objetos de especificação de consulta chamando métodos de fábrica estáticos na classe QuerySpec. Por exemplo, o método buildSmartQuerySpec cria um objeto Smart SQL que encapsula determinada sequência de caracteres de consulta:

public static QuerySpec buildSmartQuerySpec(String smartSql, int pageSize)

Para executar a consulta, passe o objeto QuerySpec retornado para o método SmartStore.query(). Essa função dá maior flexibilidade do que outras funções de fábrica de consulta porque você fornece sua própria instrução SELECT Smart SQL. O parâmetro pageSize determina quantos registros são enviados em cada página de resultados.

Para executar uma consulta em um objeto QuerySpec, passe-o para o método query() no objeto SmartStore. O código a seguir emite uma consulta que chama a função SQL COUNT. Como COUNT retorna um único valor, o único tamanho de página possível é um.

try {
    JSONArray result =
        store.query(QuerySpec.buildSmartQuerySpec(
            "select count(*) from {Accounts}", 1), 0);
    // result should be [[ n ]] if there are n employees
    Log.println(Log.INFO, "REST Success!", "\nFound " + 
        result.getString(0) + " accounts.");
 } catch (JSONException e) {
    Log.e(TAG, "Error occurred while counting the number of account records. "
        +  "Please verify validity of JSON data set.");
 }

Como gerenciar um soup

Para usar APIs de gerenciamento de soup em um aplicativo Android nativo, chame métodos na instância compartilhada do SmartStore:

SmartStore smartStore = 
    SmartStoreSDKManager.getInstance().getSmartStore();
 smartStore.clearSoup("user1Soup");

Você pode adicionar suporte SmartStore a um aplicativo nativo forcedroid facilmente. Vamos reconfigurar o arquivo de importação JSON para criar dois soups, um para cada consulta sObject. Em seguida, podemos preencher os soups ao mesmo tempo em que preenchemos o modo de exibição de lista.

  1. Abra o diretório do seu projeto no Android Studio.
  2. Na pasta app/res, crie uma pasta chamada “raw”.
  3. Clique com o botão direito do mouse em app/res/raw e selecione Novo > Arquivo. Dê ao arquivo o nome userstore.json.
  4. Adicione o seguinte texto ao novo arquivo:
    { "soups": [
        {
        "soupName": "Account",
        "indexes": [
            { "path": "Name", "type": "string"},
            { "path": "Id", "type": "string"},
            { "path": "OwnerId", "type": "string"},
            ]
        },
        {
        "soupName": "Contact",
        "indexes": [ 
            { "path": "Name", "type": "string"},
            { "path": "Id", "type": "string"},
            { "path": "OwnerId", "type": "string"},
            ]
        }
     ]}
  5. Abra MainActivity.java e importe estes arquivos:
    import com.salesforce.androidsdk.smartstore.app.SmartStoreSDKManager;
     import com.salesforce.androidsdk.smartstore.store.IndexSpec;
     import com.salesforce.androidsdk.smartstore.store.QuerySpec;
     import com.salesforce.androidsdk.smartstore.store.SmartStore;
     import com.salesforce.androidsdk.smartstore.ui.SmartStoreInspectorActivity;
  6. No início da classe MainActivity, declare uma variável privada para apontar para a instância compartilhada do SmartStore e outra para rastrear qual sObject estamos tratando:
    private SmartStore smartStore;private String objectType;
  7. No método onCreate(Bundle savedInstanceState), importe as definições de soup do seu arquivo userstore.json:
    smartStore = SmartStoreSDKManager.getInstance().getSmartStore();
     if (!smartStore.hasSoup("Account") && !smartStore.hasSoup("Contact")) {
        SmartStoreSDKManager.getInstance().setupUserStoreFromDefaultConfig();
     } else {
        // Delete existing records in preparation for new server data
        smartStore.clearSoup("Account");
        smartStore.clearSoup("Contact");
     }
  8. No método onFetchContactsClick(View v), limpe o soup Contato para evitar criar registros duplicados:
    smartStore.clearSoup("Contact");
    objectType = "Contact";
  9. No método onFetchAccountsClick(View v), limpe o soup Conta para evitar criar registros duplicados:
    smartStore.clearSoup("Account");
    objectType = "Account";
  10. No método client.sendAsync(), chame upsert() no loop for que insere a resposta JSON no objeto listAdapter:
    for (int i = 0; i < records.length(); i++) {
         listAdapter.add(records.getJSONObject(i).getString("Name"));
        try {
             smartStore.upsert((objectType, records.getJSONObject(i));
         } catch (Exception e) {
             onError(e);
         }
    }
  11. Inicie o aplicativo e verifique o seu trabalho usando o menu Ferramentas de desenvolvedor.
    • Para fazer surgir o menu, digite Command + m (Mac) ou Ctrl + m (Windows).
    • Clique em Inspecionar SmartStore.
    • Para ver uma lista dos seus soups e a quantidade de registros em cada um, clique em Soups.
  12. Nota: Se receber uma mensagem “Query: No soups found”, é provável que você tenha um erro no seu arquivo userstore.json.

Agora, você criou e preencheu dois soups do SmartStore, mas, no momento, eles não têm um objetivo claro. No mundo real, você criaria uma interface de edição para as listas de Conta e Contato e inseriria e atualizaria (upsert) as alterações do cliente no SmartStore. Quando o dispositivo do cliente tivesse conectividade novamente, você poderia mesclar as alterações no servidor com a Sincronização móvel.

Como usar o SmartStore em aplicativos híbridos

Como registrar soups com um arquivo de configuração

Em aplicativos híbridos, o Mobile SDK carrega arquivos de configuração SmartStore automaticamente. Você é responsável por colocar os arquivos de configuração no local exigido, da seguinte forma:

  1. Copie o arquivo de configuração no diretório mais alto do seu projeto híbrido www/ (por exemplo, MyProject/www/).
  2. Em uma janela de terminal ou prompt de comando do Windows, use cd para o diretório do projeto (por exemplo, MyProject/).
  3. Execute: cordova prepare

Como preencher um soup

Para obter registros do Salesforce, os aplicativos híbridos usam a função force.query() padrão na biblioteca JavaScript. Você usa o retorno de chamada de sucesso para inserir e atualizar (upsert) os dados do conjunto de registros no soup.

force.query("SELECT Name,Id FROM Contact", 
    onSuccessSfdcContacts, onErrorSfdc); 
var sfSmartstore = function() {
    return cordova.require("com.salesforce.plugin.smartstore");};
function onSuccessSfdcContacts(response) {
    logToConsole()("onSuccessSfdcContacts: received " + 
        response.totalSize + “ contacts");
    var entries = [];
    response.records.forEach(function(contact, i) {
           entries.push(contact);
    });
    if (entries.length > 0) {
        sfSmartstore().upsertSoupEntries(CONTACTS_SOUP_NAME,
            entries,
            function(items) {
                var statusTxt = "upserted: " + items.length + 
                    " contacts";
                logToConsole()(statusTxt);
            }, 
         onErrorUpsert);
    }
 }
function onErrorSfdc(param) {
    logToConsole()("onErrorSfdc: " + param);
 }
function onErrorUpsert(param) {
    logToConsole()("onErrorUpsert: " + param);
 }

Como consultar dados de soup com o Smart SQL

Nos aplicativos híbridos, você cria objetos de especificação de consulta chamando funções no objeto SmartStore do plug-in com.salesforce.plugin.smartstore. Por exemplo, a função buildSmartQuerySpec() executa uma consulta Smart SQL:

smartstore.buildSmartQuerySpec(smartSql, [pageSize])

em que smartSql é a consulta a ser executada. Essa função dá maior flexibilidade do que outras funções de fábrica de consulta porque você fornece sua própria instrução SELECT. pageSize é opcional e o padrão é 10.

O código a seguir emite uma consulta que chama a função Smart SQL COUNT em um soup chamado “funcionários”.

var querySpec = 
    navigator.smartstore.buildSmartQuerySpec(
        "select count(*) from {employees}", 1);
navigator.smartstore.runSmartQuery(querySpec, function(cursor) { 
    // result should be [[ n ]] if there are n employees
 });

Como gerenciar um soup

Cada função de gerenciamento de soup no JavaScript usa duas funções de retorno de chamada: um retorno de chamada de sucesso, que retorna os dados solicitados, e um retorno de chamada de erro. Os retornos de chamada de sucesso variam de acordo com as funções de gerenciamento de soup que os usam. Os retornos de chamada de erro usam um único argumento, que contém uma sequência de caracteres de descrição do erro. Por exemplo, você pode definir uma função de retorno de chamada de erro da seguinte forma:

function(e) { alert(“ERROR:“ + e);}

Para chamar uma função de gerenciamento de soup no JavaScript, invoque primeiro o plug-in do Cordova para inicializar o objeto do SmartStore. Use o objeto do SmartStore para chamar a função de gerenciamento de soup. O exemplo a seguir define funções de retorno de chamada nomeadas distintamente, mas você também pode defini-las em linha e anonimamente.

var sfSmartstore = function() {
    return cordova.require("com.salesforce.plugin.smartstore");};
function onSuccessRemoveSoup(param) {
    logToConsole()("onSuccessRemoveSoup: " + param);
    $("#div_soup_status_line").html("Soup removed: " 
        + SAMPLE_SOUP_NAME);
 }
function onErrorRemoveSoup(param) {
    logToConsole()("onErrorRemoveSoup: " + param);
    $("#div_soup_status_line").html("removeSoup ERROR");
 }
sfSmartstore().removeSoup(SAMPLE_SOUP_NAME,
     onSuccessRemoveSoup, 
     onErrorRemoveSoup);

Como usar o SmartStore em aplicativos React Native

Os aplicativos React Native têm muito em comum com os aplicativos híbridos. Normalmente, as funções do SmartStore para as duas plataformas compartilham assinaturas idênticas. No entanto, há várias diferenças significativas.

  • Os aplicativos React Native usam código JavaScript ES2015. Embora você possa usar a mesma sintaxe JavaScript de aplicativos híbridos, também pode aproveitar as novas convenções de codificação simplificadas.
  • Além do JavaScript, os aplicativos React Native também dão suporte a TypeScript para digitação estática. Você pode escolher quanto ou se deve usar o TypeScript.
  • Em React Native, o SmartStore não usa backbone.js.
  • Você não pode usar bibliotecas híbridas Cordova ou plug-ins no React Native. Em vez disso, importe módulos SmartStore do React Native.

Para usar a API do SmartStore, importe o módulo smartstore. Para usar a API do Salesforce e, principalmente, para fazer consultas e recuperar registros do Salesforce, importe o módulo net. Você pode importar os dois módulos em uma mesma instrução.

import {net, smartstore} from 'react-native-force';

Como registrar um soup

Para o React Native, você usa código JavaScript em vez de arquivos de configuração para definir soups do SmartStore. Por exemplo:

smartstore.registerSoup(false,
    "contacts", 
    [ {path:"Id", type:"string"}, 
    {path:"FirstName", type:"full_text"}, 
    {path:"LastName", type:"full_text"},    
    {path:"__local__", type:"string"} ],
    () => syncDown()
 );

Como preencher um soup

Para preencher seu soup com dados do Salesforce, comece consultando registros usando a API do Salesforce padrão. O módulo net oferece um conjunto de funções wrapper que simplificam as chamadas de rede. Você transmite uma sequência de caracteres de consulta e retornos de chamada de sucesso e erro. No retorno de chamada de sucesso, use o módulo smartstore para fazer inserir e atualizar (upsert ) registros da resposta da consulta no soup. (Se essa estratégia soa familiar, você deve ter lido a seção de híbrido!)

net.query("SELECT Name,Id FROM Contact", 
        onSuccessSfdcContacts, onErrorSfdc);

Aqui está um exemplo de retorno de chamada de sucesso:

function onSuccessSfdcContacts(response) {
    logToConsole()("onSuccessSfdcContacts: received " + 
        response.totalSize + “ contacts");
    var entries = [];
    $.each(response.records, function(i, contact) {
           entries.push(contact);
           logToConsole()("name: " + contact.Name);
    });
    if (entries.length > 0) {
        smartstore().upsertSoupEntries(CONTACTS_SOUP_NAME,
            entries,
            function(items) {
                var statusTxt = "upserted: " + items.length + 
                    " contacts";
                logToConsole()(statusTxt);
            }, 
            onErrorUpsert);
    }
 }

Como consultar dados de soup com o Smart SQL

No React Native, crie objetos de especificação de consulta chamando funções no módulo smartstore. Por exemplo, a função buildSmartQuerySpec() constrói um objeto de consulta Smart SQL:

buildSmartQuerySpec(smartSql, [pageSize])

Nessa função, smartSql é a consulta a ser executada. Essa função dá maior flexibilidade do que outras funções de consulta de fábrica porque você fornece sua própria instrução SELECT. O pageSize é opcional e o padrão é 10.

Depois de criar o objeto de consulta smart, transmita-a para a função runSmartQuery() com um retorno de chamada de sucesso para lidar com a resposta. O código a seguir cria e executa uma consulta que chama a função SQL COUNT.

var querySpec = 
    smartstore.buildSmartQuerySpec(
        "select count(*) from {employees}", 1);
// Note that the first parameter--a storeConfig object, or a Boolean indicating whether to use 
// the default global store or the default user store--is required in React Native apps
// but is optional in hybrid apps
smartstore.runSmartQuery(false, querySpec, function(cursor) { 
    // result should be [[ n ]] if there are n employees
 });

Como usar as funções de gerenciamento do SmartStore

As funções de gerenciamento de soup seguem o mesmo padrão de outras funções React Native. Defina os retornos de chamada de sucesso e erro e chame a função no módulo smartstore. A quantidade de parâmetros transmitidos ao retorno de chamada de sucesso podem variar de acordo com a função. Os retornos de chamada de erro sempre usam apenas um argumento de sequência de caracteres de descrição de erro.

Recursos

Continue a aprender de graça!
Inscreva-se em uma conta para continuar.
O que você ganha com isso?
  • Receba recomendações personalizadas para suas metas de carreira
  • Pratique suas habilidades com desafios práticos e testes
  • Monitore e compartilhe seu progresso com os empregadores
  • Conecte-se a orientação e oportunidades de carreira