Ricerca app

AppSearch è una soluzione di ricerca on-device ad alte prestazioni per la gestione dei dati strutturati archiviati localmente. Contiene API per l'indicizzazione e il recupero dei dati utilizzando la ricerca a testo intero. Le applicazioni possono utilizzare AppSearch per offrire funzionalità di ricerca in-app personalizzate, consentendo agli utenti di cercare contenuti anche offline.

Diagramma che illustra l'indicizzazione e la ricerca in AppSearch

AppSearch offre le seguenti funzionalità:

  • Un'implementazione di archiviazione rapida, mobile-first e con un utilizzo ridotto di I/O
  • Indicizzazione e query altamente efficienti su set di dati di grandi dimensioni
  • Supporto multilingue, ad esempio inglese e spagnolo
  • Ranking di pertinenza e punteggio di utilizzo

Grazie al minore utilizzo di I/O, AppSearch offre una latenza inferiore per l'indicizzazione e la ricerca su set di dati di grandi dimensioni rispetto a SQLite. AppSearch semplifica le query tra tipi supportando query singole, mentre SQLite unisce i risultati di più tabelle.

Per illustrare le funzionalità di AppSearch, prendiamo l'esempio di un'applicazione musicale che gestisce i brani preferiti degli utenti e consente loro di cercarli facilmente. Gli utenti ascoltano musica di tutto il mondo con titoli di brani in diverse lingue, per le quali AppSearch supporta in modo nativo l'indicizzazione e l'esecuzione di query. Quando l'utente cerca un brano per titolo o nome dell'artista, l'applicazione passa semplicemente la richiesta ad AppSearch per recuperare i brani corrispondenti in modo rapido ed efficiente. L'applicazione mostra i risultati, consentendo agli utenti di iniziare rapidamente a riprodurre i loro brani preferiti.

Configurazione

Per utilizzare AppSearch nella tua applicazione, aggiungi le seguenti dipendenze al file build.gradle dell'applicazione:

Alla moda

dependencies {
    def appsearch_version = "1.2.0-alpha02"

    implementation "androidx.appsearch:appsearch:$appsearch_version"
    // Use kapt instead of annotationProcessor if writing Kotlin classes
    annotationProcessor "androidx.appsearch:appsearch-compiler:$appsearch_version"

    implementation "androidx.appsearch:appsearch-local-storage:$appsearch_version"
    // PlatformStorage is compatible with Android 12+ devices and supports sharing data
    // with other apps. Feature support varies by device. Before calling an API that
    // requires a feature, check Features.isFeatureSupported().
    implementation "androidx.appsearch:appsearch-platform-storage:$appsearch_version"

    // PlayServicesStorage is compatible with all devices that support Google Play Services on
    // all API levels. It offers similar capabilities to PlatformStorage and is the
    // recommended solution for lower API levels on which PlatformStorage is not supported.
    implementation "androidx.appsearch:appsearch-play-services-storage:$appsearch_version"
}

Kotlin

dependencies {
    val appsearch_version = "1.2.0-alpha02"

    implementation("androidx.appsearch:appsearch:$appsearch_version")
    // Use annotationProcessor instead of kapt if writing Java classes
    kapt("androidx.appsearch:appsearch-compiler:$appsearch_version")

    implementation("androidx.appsearch:appsearch-local-storage:$appsearch_version")
    // PlatformStorage is compatible with Android 12+ devices and supports sharing data
    // with other apps. Feature support varies by device. Before calling an API that
    // requires a feature, check Features.isFeatureSupported().
    implementation("androidx.appsearch:appsearch-platform-storage:$appsearch_version")

    // PlayServicesStorage is compatible with all devices that support Google Play Services on
    // all API levels. It offers similar capabilities to PlatformStorage and is the
    // recommended solution for lower API levels on which PlatformStorage is not supported.
    implementation("androidx.appsearch:appsearch-play-services-storage:$appsearch_version")

}

Concetti di AppSearch

Il seguente diagramma illustra i concetti di AppSearch e le relative interazioni.

Diagramma di un'applicazione client e delle sue interazioni con i seguenti concetti di AppSearch: database AppSearch, schema, tipi di schema, documenti, sessione e ricerca. Figura 1. Diagramma dei concetti di AppSearch: database AppSearch, schema, tipi di schema, documenti, sessione e ricerca.

Database e sessione

Un database AppSearch è una raccolta di documenti conforme allo schema del database. Le applicazioni client creano un database fornendo il contesto dell'applicazione e un nome del database. I database possono essere aperti solo dall'applicazione che li ha creati. Quando viene aperto un database, viene restituita una sessione per interagire con il database. La sessione è il punto di accesso per chiamare le API AppSearch e rimane aperta finché non viene chiusa dall'applicazione client.

Schema e tipi di schema

Uno schema rappresenta la struttura organizzativa dei dati all'interno di un database AppSearch.

Lo schema è composto da tipi di schema che rappresentano tipi di dati univoci. I tipi di schema sono costituiti da proprietà che contengono un nome, un tipo di dati e una cardinalità. Una volta aggiunto un tipo di schema allo schema del database, è possibile creare e aggiungere al database i documenti di quel tipo di schema.

Documenti

In AppSearch, un'unità di dati è rappresentata come un documento. Ogni documento in un database AppSearch è identificato in modo univoco dal relativo spazio dei nomi e dall'ID. Gli spazi dei nomi vengono utilizzati per separare i dati provenienti da origini diverse quando è necessario eseguire query su una sola origine, ad esempio gli account utente.

I documenti contengono un timestamp di creazione, un TTL (Time to Live) e un punteggio che può essere utilizzato per il ranking durante il recupero. A un documento viene inoltre assegnato un tipo di schema che descrive le proprietà dei dati aggiuntive che il documento deve avere.

Una classe di documenti è un'astrazione di un documento. Contiene campi annotati che rappresentano i contenuti di un documento. Per impostazione predefinita, il nome della classe del documento imposta il nome del tipo di schema.

I documenti vengono indicizzati e possono essere cercati fornendo una query. Un documento viene trovato e incluso nei risultati di ricerca se contiene i termini della query o corrisponde a un'altra specifica di ricerca. I risultati vengono ordinati in base al punteggio e alla strategia di ranking. I risultati di ricerca sono rappresentati da pagine che puoi recuperare in sequenza.

AppSearch offre personalizzazioni per la ricerca, come filtri, configurazione delle dimensioni della pagina e snippet.

Spazio di archiviazione della piattaforma, spazio di archiviazione locale o spazio di archiviazione di Play Services

AppSearch offre tre soluzioni di archiviazione: LocalStorage, PlatformStorage e PlayServicesStorage. Con LocalStorage, la tua applicazione gestisce un indice specifico dell'app che si trova nella directory dei dati dell'applicazione. Con PlatformStorage e PlayServicesStorage, la tua applicazione contribuisce a un indice centrale a livello di sistema. L'indice di PlatformStorage è ospitato nel server di sistema, mentre l'indice di PlayServicesStorage è ospitato nello spazio di archiviazione di Google Play Services. L'accesso ai dati all'interno di questi indici centrali è limitato ai dati forniti dalla tua applicazione e ai dati che sono stati esplicitamente condivisi con te da un'altra applicazione. Tutte queste opzioni di archiviazione condividono la stessa API e possono essere intercambiate in base alla versione del dispositivo.

Tieni presente che il supporto delle funzionalità varia in base all'opzione di archiviazione e al dispositivo. Per saperne di più, consulta Verifica la disponibilità delle funzionalità.

Il seguente codice crea una sessione PlatformStorage su Android 12 (livello API 31) e versioni successive e una sessione PlayServicesStorage o LocalStorage su versioni precedenti:

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    appSearchSessionFuture.setFuture(
        PlatformStorage.createSearchSession(
            PlatformStorage.SearchContext.Builder(mContext, DATABASE_NAME)
               .build()
        )
    )
} else {
    if (usePlayServicesStorageBelowS) {
        appSearchSessionFuture.setFuture(
            PlayServicesStorage.createSearchSession(
                PlayServicesStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                    .build()
            )
        )
    } else {
        appSearchSessionFuture.setFuture(
            LocalStorage.createSearchSession(
                LocalStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                    .build()
            )
        )
    }
}

Java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    mAppSearchSessionFuture.setFuture(PlatformStorage.createSearchSession(
            new PlatformStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                    .build()));
} else {
    if (usePlayServicesStorageBelowS) {
        mAppSearchSessionFuture.setFuture(PlayServicesStorage.createSearchSession(
                new PlayServicesStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                        .build()));
    } else {
        mAppSearchSessionFuture.setFuture(LocalStorage.createSearchSession(
                new LocalStorage.SearchContext.Builder(mContext, DATABASE_NAME)
                        .build()));
    }
}

Utilizzando PlatformStorage e PlayServicesStorage, la tua applicazione può condividere i dati in modo sicuro con altre applicazioni per consentire loro di eseguire ricerche anche nei dati della tua app. La condivisione dei dati dell'applicazione in sola lettura viene concessa utilizzando un handshake del certificato per garantire che l'altra applicazione disponga dell'autorizzazione per leggere i dati. Scopri di più su questa API nella documentazione per setSchemaTypeVisibilityForPackage().

Inoltre, con PlatformStorage, i dati indicizzati possono essere visualizzati sulle piattaforme della UI di sistema. Le applicazioni possono disattivare la visualizzazione di alcuni o tutti i loro dati sulle piattaforme della UI di sistema. Scopri di più su questa API nella documentazione di setSchemaTypeDisplayedBySystem().

Funzionalità LocalStorage (compatibile con Android 5.0 e versioni successive) PlatformStorage (compatibile con Android 12 e versioni successive) PlayServicesStorage (compatibile con Android 5.0 e versioni successive)
Ricerca a testo intero efficiente
Supporto di più lingue
Dimensioni binarie ridotte
Condivisione dei dati tra applicazioni
Capacità di visualizzare i dati sulle piattaforme della UI di sistema
È possibile indicizzare un numero illimitato di documenti di qualsiasi dimensione
Operazioni più rapide senza latenza aggiuntiva del binder

Ci sono altri compromessi da considerare quando si sceglie tra LocalStorage e PlatformStorage. Poiché PlatformStorage aggrega le API Jetpack sul servizio di sistema AppSearch, l'impatto sulle dimensioni dell'APK è minimo rispetto all'utilizzo di LocalStorage. Tuttavia, ciò significa anche che le operazioni di AppSearch comportano una latenza aggiuntiva del binder quando viene chiamato il servizio di sistema AppSearch. Con PlatformStorage, AppSearch limita il numero e le dimensioni dei documenti che un'applicazione può indicizzare per garantire un indice centrale efficiente. PlayServicesStorage ha anche le stesse limitazioni di PlatformStorage ed è supportato solo sui dispositivi con Google Play Services.

Verificare le funzionalità disponibili

Sebbene tutte le opzioni di archiviazione condividano la stessa API, alcune funzionalità non sono disponibili con tutte le opzioni di archiviazione o su tutti i dispositivi. Nel riferimento API, l'annotazione @RequiresFeature identifica le API che richiedono una di queste funzionalità e la classe Features definisce una costante per ogni funzionalità. Ad esempio, INDEXING_TYPE_RANGE richiede Features.NUMERIC_SEARCH.

Per PlatformStorage, il supporto delle funzionalità dipende dalla versione di Android del dispositivo. A partire da Android 13 (livello API 33), il supporto delle funzionalità dipende anche dagli aggiornamenti di sistema Google Play ricevuti dal dispositivo. Ad esempio, PlatformStorage supporta la ricerca numerica (Features.NUMERIC_SEARCH), la ricerca verbatim (Features.VERBATIM_SEARCH) e i join (Features.JOIN_SPEC_AND_QUALIFIED_ID) solo sui seguenti dispositivi:

  • Dispositivi con Android 14 (livello API 34) o versioni successive.
  • Dispositivi con Android 13 (livello API 33) che hanno ricevuto l'aggiornamento di sistema Google Play richiesto.

Queste funzionalità non sono supportate sui dispositivi con Android 12 o Android 12L (livelli API 31 e 32).

Anche il numero massimo di proprietà indicizzate in un documento varia in base al dispositivo e all'opzione di archiviazione. Per ottenere il limite in fase di runtime, chiama getMaxIndexedProperties().

Non fare affidamento solo sulla versione di Android per determinare il supporto delle funzionalità. Prima di chiamare un'API che richiede una funzionalità, verifica che questa sia supportata chiamando isFeatureSupported() sull'oggetto Features restituito da AppSearchSession.getFeatures(). Se una funzionalità richiesta non è supportata, l'operazione non va a buon fine e viene generata un'eccezione. Un esempio di caso di errore è l'impostazione di uno schema che include una proprietà INDEXING_TYPE_RANGE che non funziona sui dispositivi che non supportano Features.NUMERIC_SEARCH.

Il seguente codice verifica se un AppSearchSession aperto supporta la ricerca numerica:

Kotlin

val features = session.features
if (features.isFeatureSupported(Features.NUMERIC_SEARCH)) {
    // Numeric search is supported. You can index properties with
    // LongPropertyConfig.INDEXING_TYPE_RANGE and enable numeric search with
    // SearchSpec.Builder.setNumericSearchEnabled(true).
} else {
    // Numeric search isn't supported. Set a schema without range-indexed
    // properties, or switch to a different storage option.
}

Java

Features features = session.getFeatures();
if (features.isFeatureSupported(Features.NUMERIC_SEARCH)) {
    // Numeric search is supported. You can index properties with
    // LongPropertyConfig.INDEXING_TYPE_RANGE and enable numeric search with
    // SearchSpec.Builder.setNumericSearchEnabled(true).
} else {
    // Numeric search isn't supported. Set a schema without range-indexed
    // properties, or switch to a different storage option.
}

Inizia a utilizzare AppSearch

L'esempio in questa sezione mostra come utilizzare le API AppSearch per l'integrazione con un'ipotetica applicazione per prendere appunti.

Scrivi una classe di documento

Il primo passaggio per l'integrazione con AppSearch consiste nello scrivere una classe di documento per descrivere i dati da inserire nel database. Contrassegna una classe come classe di documento utilizzando l'annotazione @Document.Puoi utilizzare le istanze della classe di documento per inserire i documenti nel database e recuperarli.

Il codice seguente definisce una classe di documento Note con un campo annotato @Document.StringProperty per l'indicizzazione del testo di un oggetto Note.

Kotlin

@Document
public data class Note(

    // Required field for a document class. All documents MUST have a namespace.
    @Document.Namespace
    val namespace: String,

    // Required field for a document class. All documents MUST have an Id.
    @Document.Id
    val id: String,

    // Optional field for a document class, used to set the score of the
    // document. If this is not included in a document class, the score is set
    // to a default of 0.
    @Document.Score
    val score: Int,

    // Optional field for a document class, used to index a note's text for this
    // document class.
    @Document.StringProperty(indexingType = AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES)
    val text: String
)

Java

@Document
public class Note {

  // Required field for a document class. All documents MUST have a namespace.
  @Document.Namespace
  private final String namespace;

  // Required field for a document class. All documents MUST have an Id.
  @Document.Id
  private final String id;

  // Optional field for a document class, used to set the score of the
  // document. If this is not included in a document class, the score is set
  // to a default of 0.
  @Document.Score
  private final int score;

  // Optional field for a document class, used to index a note's text for this
  // document class.
  @Document.StringProperty(indexingType = StringPropertyConfig.INDEXING_TYPE_PREFIXES)
  private final String text;

  Note(@NonNull String id, @NonNull String namespace, int score, @NonNull String text) {
    this.id = Objects.requireNonNull(id);
    this.namespace = Objects.requireNonNull(namespace);
    this.score = score;
    this.text = Objects.requireNonNull(text);
  }

  @NonNull
  public String getNamespace() {
    return namespace;
  }

  @NonNull
  public String getId() {
    return id;
  }

  public int getScore() {
    return score;
  }

  @NonNull
  public String getText() {
     return text;
  }
}

Apri un database

Devi creare un database prima di lavorare con i documenti. Il seguente codice crea un nuovo database con il nome notes_app e ottiene un ListenableFuture per un AppSearchSession, che rappresenta la connessione al database e fornisce le API per le operazioni sul database.

Kotlin

val context: Context = getApplicationContext()
val sessionFuture = LocalStorage.createSearchSession(
    LocalStorage.SearchContext.Builder(context, /*databaseName=*/"notes_app")
    .build()
)

Java

Context context = getApplicationContext();
ListenableFuture<AppSearchSession> sessionFuture = LocalStorage.createSearchSession(
       new LocalStorage.SearchContext.Builder(context, /*databaseName=*/ "notes_app")
               .build()
);

Imposta uno schema

Devi impostare uno schema prima di poter inserire e recuperare documenti dal database. Lo schema del database è costituito da diversi tipi di dati strutturati, chiamati "tipi di schema". Il seguente codice imposta lo schema fornendo la classe del documento come tipo di schema.

Kotlin

val setSchemaRequest = SetSchemaRequest.Builder().addDocumentClasses(Note::class.java)
    .build()
val setSchemaFuture = Futures.transformAsync(
    sessionFuture,
    { session ->
        session?.setSchema(setSchemaRequest)
    }, mExecutor
)

Java

SetSchemaRequest setSchemaRequest = new SetSchemaRequest.Builder().addDocumentClasses(Note.class)
       .build();
ListenableFuture<SetSchemaResponse> setSchemaFuture =
       Futures.transformAsync(sessionFuture, session -> session.setSchema(setSchemaRequest), mExecutor);

Inserisci un documento nel database

Una volta aggiunto un tipo di schema, puoi aggiungere documenti di quel tipo al database. Il codice seguente crea un documento di tipo di schema Note utilizzando il builder di classi di documenti Note. Imposta lo spazio dei nomi del documento user1 per rappresentare un utente arbitrario di questo esempio. Il documento viene quindi inserito nel database e viene collegato un listener per elaborare il risultato dell'operazione put.

Kotlin

val note = Note(
    namespace="user1",
    id="noteId",
    score=10,
    text="Buy fresh fruit"
)

val putRequest = PutDocumentsRequest.Builder().addDocuments(note).build()
val putFuture = Futures.transformAsync(
    sessionFuture,
    { session ->
        session?.put(putRequest)
    }, mExecutor
)

Futures.addCallback(
    putFuture,
    object : FutureCallback<AppSearchBatchResult<String, Void>?> {
        override fun onSuccess(result: AppSearchBatchResult<String, Void>?) {

            // Gets map of successful results from Id to Void
            val successfulResults = result?.successes

            // Gets map of failed results from Id to AppSearchResult
            val failedResults = result?.failures
        }

        override fun onFailure(t: Throwable) {
            Log.e(TAG, "Failed to put documents.", t)
        }
    },
    mExecutor
)

Java

Note note = new Note(/*namespace=*/"user1", /*id=*/
                "noteId", /*score=*/ 10, /*text=*/ "Buy fresh fruit!");

PutDocumentsRequest putRequest = new PutDocumentsRequest.Builder().addDocuments(note)
       .build();
ListenableFuture<AppSearchBatchResult<String, Void>> putFuture =
       Futures.transformAsync(sessionFuture, session -> session.put(putRequest), mExecutor);

Futures.addCallback(putFuture, new FutureCallback<AppSearchBatchResult<String, Void>>() {
   @Override
   public void onSuccess(@Nullable AppSearchBatchResult<String, Void> result) {

     // Gets map of successful results from Id to Void
     Map<String, Void> successfulResults = result.getSuccesses();

     // Gets map of failed results from Id to AppSearchResult
     Map<String, AppSearchResult<Void>> failedResults = result.getFailures();
   }

   @Override
   public void onFailure(@NonNull Throwable t) {
      Log.e(TAG, "Failed to put documents.", t);
   }
}, mExecutor);

Puoi cercare i documenti indicizzati utilizzando le operazioni di ricerca descritte in questa sezione. Il seguente codice esegue query per il termine "fruit" nel database per i documenti che appartengono allo spazio dei nomi user1.

Kotlin

val searchSpec = SearchSpec.Builder()
    .addFilterNamespaces("user1")
    .build();

val searchFuture = Futures.transform(
    sessionFuture,
    { session ->
        session?.search("fruit", searchSpec)
    },
    mExecutor
)
Futures.addCallback(
    searchFuture,
    object : FutureCallback<SearchResults> {
        override fun onSuccess(searchResults: SearchResults?) {
            iterateSearchResults(searchResults)
        }

        override fun onFailure(t: Throwable?) {
            Log.e("TAG", "Failed to search notes in AppSearch.", t)
        }
    },
    mExecutor
)

Java

SearchSpec searchSpec = new SearchSpec.Builder()
       .addFilterNamespaces("user1")
       .build();

ListenableFuture<SearchResults> searchFuture =
       Futures.transform(sessionFuture, session -> session.search("fruit", searchSpec),
       mExecutor);

Futures.addCallback(searchFuture,
       new FutureCallback<SearchResults>() {
           @Override
           public void onSuccess(@Nullable SearchResults searchResults) {
               iterateSearchResults(searchResults);
           }

           @Override
           public void onFailure(@NonNull Throwable t) {
               Log.e(TAG, "Failed to search notes in AppSearch.", t);
           }
       }, mExecutor);

Esegui l'iterazione dei risultati di ricerca

Le ricerche restituiscono un'istanza SearchResults, che consente di accedere alle pagine degli oggetti SearchResult. Ogni SearchResult contiene il GenericDocument corrispondente, la forma generale di un documento in cui vengono convertiti tutti i documenti. Il seguente codice recupera la prima pagina dei risultati di ricerca e converte il risultato in un documento Note.

Kotlin

Futures.transform(
    searchResults?.nextPage,
    { page: List<SearchResult>? ->
        // Gets GenericDocument from SearchResult.
        val genericDocument: GenericDocument = page!![0].genericDocument
        val schemaType = genericDocument.schemaType
        val note: Note? = try {
            if (schemaType == "Note") {
                // Converts GenericDocument object to Note object.
                genericDocument.toDocumentClass(Note::class.java)
            } else null
        } catch (e: AppSearchException) {
            Log.e(
                TAG,
                "Failed to convert GenericDocument to Note",
                e
            )
            null
        }
        note
    },
    mExecutor
)

Java

Futures.transform(searchResults.getNextPage(), page -> {
  // Gets GenericDocument from SearchResult.
  GenericDocument genericDocument = page.get(0).getGenericDocument();
  String schemaType = genericDocument.getSchemaType();

  Note note = null;

  if (schemaType.equals("Note")) {
    try {
      // Converts GenericDocument object to Note object.
      note = genericDocument.toDocumentClass(Note.class);
    } catch (AppSearchException e) {
      Log.e(TAG, "Failed to convert GenericDocument to Note", e);
    }
  }

  return note;
}, mExecutor);

Rimuovi un documento

Quando l'utente elimina una nota, l'applicazione elimina il documento Note corrispondente dal database. In questo modo, la nota non verrà più visualizzata nelle query. Il codice seguente effettua una richiesta esplicita di rimozione del documento Note dal database in base all'ID.

Kotlin

val removeRequest = RemoveByDocumentIdRequest.Builder("user1")
    .addIds("noteId")
    .build()

val removeFuture = Futures.transformAsync(
    sessionFuture, { session ->
        session?.remove(removeRequest)
    },
    mExecutor
)

Java

RemoveByDocumentIdRequest removeRequest = new RemoveByDocumentIdRequest.Builder("user1")
       .addIds("noteId")
       .build();

ListenableFuture<AppSearchBatchResult<String, Void>> removeFuture =
       Futures.transformAsync(sessionFuture, session -> session.remove(removeRequest), mExecutor);

Persistenza su disco

Gli aggiornamenti a un database devono essere salvati periodicamente su disco chiamando requestFlush(). Il codice seguente chiama requestFlush() con un listener per determinare se la chiamata è andata a buon fine.

Kotlin

val requestFlushFuture = Futures.transformAsync(
    sessionFuture,
    { session -> session?.requestFlush() }, mExecutor
)

Futures.addCallback(requestFlushFuture, object : FutureCallback<Void?> {
    override fun onSuccess(result: Void?) {
        // Success! Database updates have been persisted to disk.
    }

    override fun onFailure(t: Throwable) {
        Log.e(TAG, "Failed to flush database updates.", t)
    }
}, mExecutor)

Java

ListenableFuture<Void> requestFlushFuture = Futures.transformAsync(sessionFuture,
        session -> session.requestFlush(), mExecutor);

Futures.addCallback(requestFlushFuture, new FutureCallback<Void>() {
    @Override
    public void onSuccess(@Nullable Void result) {
        // Success! Database updates have been persisted to disk.
    }

    @Override
    public void onFailure(@NonNull Throwable t) {
        Log.e(TAG, "Failed to flush database updates.", t);
    }
}, mExecutor);

Chiudi una sessione

Un AppSearchSession deve essere chiuso quando un'applicazione non chiama più operazioni del database. Il seguente codice chiude la sessione AppSearch aperta in precedenza e salva tutti gli aggiornamenti sul disco.

Kotlin

val closeFuture = Futures.transform<AppSearchSession, Unit>(sessionFuture,
    { session ->
        session?.close()
        Unit
    }, mExecutor
)

Java

ListenableFuture<Void> closeFuture = Futures.transform(sessionFuture, session -> {
   session.close();
   return null;
}, mExecutor);

Risorse aggiuntive

Per scoprire di più su AppSearch, consulta le seguenti risorse aggiuntive:

Esempi

Invia il tuo feedback

Condividi con noi il tuo feedback e le tue idee tramite queste risorse:

Issue Tracker

Segnala i bug per consentirci di risolverli.