AppSearch

AppSearch est une solution de recherche hautes performances sur l'appareil qui permet de gérer les données structurées stockées localement. Elle contient des API permettant d'indexer et de récupérer les données à l'aide de la recherche en texte intégral. Les applications peuvent utiliser AppSearch pour proposer des fonctionnalités de recherche in-app personnalisées, permettant aux utilisateurs de rechercher du contenu même lorsqu'ils sont hors connexion.

Schéma illustrant l'indexation et la recherche dans AppSearch

AppSearch propose les fonctionnalités suivantes :

  • Une implémentation de stockage rapide, axée sur les mobiles et utilisant peu d'E/S
  • Indexation et interrogation très efficaces sur de grands ensembles de données
  • Compatibilité multilingue (anglais et espagnol, par exemple)
  • Classement par pertinence et score d'utilisation

En raison d'une utilisation d'E/S plus faible, AppSearch offre une latence plus faible pour l'indexation et la recherche sur de grands ensembles de données par rapport à SQLite. AppSearch simplifie les requêtes de types croisés en acceptant les requêtes uniques, tandis que SQLite fusionne les résultats de plusieurs tables.

Pour illustrer les fonctionnalités d'AppSearch, prenons l'exemple d'une application musicale qui gère les titres préférés des utilisateurs et leur permet de les rechercher facilement. Les utilisateurs écoutent de la musique du monde entier avec des titres de chansons dans différentes langues, pour lesquelles AppSearch prend en charge l'indexation et l'interrogation de manière native. Lorsque l'utilisateur recherche un titre par son nom ou par le nom de l'artiste, l'application transmet simplement la requête à AppSearch pour récupérer rapidement et efficacement les titres correspondants. L'application affiche les résultats, ce qui permet aux utilisateurs de lancer rapidement la lecture de leurs titres préférés.

Configuration

Pour utiliser AppSearch dans votre application, ajoutez les dépendances suivantes au fichier build.gradle de votre application :

Groovy

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

}

Concepts AppSearch

Le schéma suivant illustre les concepts d'AppSearch et leurs interactions.

Diagramme d'une application cliente et de ses interactions avec les concepts AppSearch suivants : base de données AppSearch, schéma, types de schémas, documents, session et recherche. Figure 1 : Diagramme des concepts AppSearch : base de données AppSearch, schéma, types de schémas, documents, session et recherche.

Base de données et session

Une base de données AppSearch est une collection de documents conforme au schéma de la base de données. Les applications clientes créent une base de données en fournissant leur contexte d'application et un nom de base de données. Les bases de données ne peuvent être ouvertes que par l'application qui les a créées. Lorsqu'une base de données est ouverte, une session est renvoyée pour interagir avec elle. La session est le point d'entrée pour appeler les API AppSearch et reste ouverte jusqu'à ce qu'elle soit fermée par l'application cliente.

Schéma et types de schémas

Un schéma représente la structure organisationnelle des données dans une base de données AppSearch.

Le schéma est composé de types de schémas qui représentent des types de données uniques. Les types de schémas sont constitués de propriétés contenant un nom, un type de données et une cardinalité. Une fois qu'un type de schéma est ajouté au schéma de la base de données, les documents de ce type de schéma peuvent être créés et ajoutés à la base de données.

Documents

Dans AppSearch, une unité de données est représentée sous la forme d'un document. Chaque document d'une base de données AppSearch est identifié de manière unique par son espace de noms et son ID. Les espaces de noms permettent de séparer les données de différentes sources lorsqu'une seule source doit être interrogée, comme les comptes utilisateur.

Les documents contiennent un code temporel de création, une valeur TTL (Time To Live) et un score qui peut être utilisé pour le classement lors de la récupération. Un type de schéma est également attribué à un document. Il décrit les propriétés de données supplémentaires que le document doit posséder.

Une classe de document est une abstraction d'un document. Il contient des champs annotés qui représentent le contenu d'un document. Par défaut, le nom de la classe de document définit le nom du type de schéma.

Les documents sont indexés et peuvent être recherchés en fournissant une requête. Un document est mis en correspondance et inclus dans les résultats de recherche s'il contient les termes de la requête ou s'il correspond à une autre spécification de recherche. Les résultats sont classés en fonction de leur score et de leur stratégie de classement. Les résultats de recherche sont représentés par des pages que vous pouvez récupérer de manière séquentielle.

AppSearch propose des personnalisations pour la recherche, telles que des filtres, la configuration de la taille de la page et l'extraction d'extraits.

Stockage de la plate-forme, stockage local ou stockage des services Play

AppSearch propose trois solutions de stockage : LocalStorage, PlatformStorage et PlayServicesStorage. Avec LocalStorage, votre application gère un index spécifique à l'application qui se trouve dans le répertoire de données de votre application. Avec PlatformStorage et PlayServicesStorage, votre application contribue à un index central à l'échelle du système. L'index de PlatformStorage est hébergé sur le serveur système, et celui de PlayServicesStorage est hébergé dans l'espace de stockage des services Google Play. L'accès aux données de ces index centraux est limité aux données fournies par votre application et à celles qui ont été explicitement partagées avec vous par une autre application. Toutes ces options de stockage partagent la même API et peuvent être interchangées en fonction de la version de l'appareil.

N'oubliez pas que la compatibilité des fonctionnalités varie selon l'option de stockage et l'appareil. Pour en savoir plus, consultez Vérifier la disponibilité des fonctionnalités.

Le code suivant crée une session PlatformStorage sur Android 12 (niveau d'API 31) ou version ultérieure, et une session PlayServicesStorage ou LocalStorage sur les versions antérieures :

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

Grâce à PlatformStorage et PlayServicesStorage, votre application peut partager des données de manière sécurisée avec d'autres applications pour leur permettre d'effectuer des recherches dans les données de votre application. Le partage de données d'application en lecture seule est accordé à l'aide d'un handshake de certificat pour s'assurer que l'autre application est autorisée à lire les données. Pour en savoir plus sur cette API, consultez la documentation sur setSchemaTypeVisibilityForPackage().

De plus, avec PlatformStorage, les données indexées peuvent être affichées sur les surfaces de l'UI du système. Les applications peuvent désactiver l'affichage de tout ou partie de leurs données sur les surfaces de l'UI du système. Pour en savoir plus sur cette API, consultez la documentation sur setSchemaTypeDisplayedBySystem().

Fonctionnalités LocalStorage (compatible avec Android 5.0 ou version ultérieure) PlatformStorage (compatible avec Android 12 ou version ultérieure) PlayServicesStorage (compatible avec Android 5.0 ou version ultérieure)
Recherche en texte intégral efficace
Compatibilité multilingue
Taille binaire réduite
Partage de données d'application à application
Capacité à afficher des données sur les surfaces de l'UI du système
Taille et nombre de documents illimités pouvant être indexés
Opérations plus rapides sans latence de liaison supplémentaire

D'autres compromis sont à prendre en compte lorsque vous choisissez entre LocalStorage et PlatformStorage. Comme PlatformStorage encapsule les API Jetpack sur le service système AppSearch, l'impact sur la taille de l'APK est minime par rapport à l'utilisation de LocalStorage. Toutefois, cela signifie également que les opérations AppSearch entraînent une latence de liaison supplémentaire lors de l'appel du service système AppSearch. Avec PlatformStorage, AppSearch limite le nombre et la taille des documents qu'une application peut indexer afin de garantir l'efficacité de l'index central. PlayServicesStorage présente également les mêmes limites que PlatformStorage et n'est compatible qu'avec les appareils dotés des services Google Play.

Vérifier la disponibilité des fonctionnalités

Bien que toutes les options de stockage partagent la même API, certaines fonctionnalités ne sont pas disponibles avec toutes les options de stockage ou sur tous les appareils. Dans la documentation de référence de l'API, l'annotation @RequiresFeature identifie les API qui nécessitent l'une de ces fonctionnalités, et la classe Features définit une constante pour chaque fonctionnalité. Par exemple, INDEXING_TYPE_RANGE nécessite Features.NUMERIC_SEARCH.

Pour PlatformStorage, la compatibilité des fonctionnalités dépend de la version d'Android de l'appareil. À partir d'Android 13 (niveau d'API 33), la compatibilité des fonctionnalités dépend également des mises à jour du système Google Play reçues par l'appareil. Par exemple, PlatformStorage n'est compatible avec la recherche numérique (Features.NUMERIC_SEARCH), la recherche textuelle (Features.VERBATIM_SEARCH) et les jointures (Features.JOIN_SPEC_AND_QUALIFIED_ID) que sur les appareils suivants :

  • Appareils équipés d'Android 14 (niveau d'API 34) ou version ultérieure.
  • Appareils équipés d'Android 13 (niveau d'API 33) et ayant reçu la mise à jour du système Google Play requise.

Ces fonctionnalités ne sont pas compatibles avec les appareils équipés d'Android 12 ou Android 12L (niveaux d'API 31 et 32).

Le nombre maximal de propriétés indexées dans un document varie également selon l'appareil et l'option de stockage. Pour obtenir la limite au moment de l'exécution, appelez getMaxIndexedProperties().

Ne vous fiez pas uniquement à la version d'Android pour déterminer la compatibilité des fonctionnalités. Avant d'appeler une API qui nécessite une fonctionnalité, vérifiez que celle-ci est compatible en appelant isFeatureSupported() sur l'objet Features renvoyé par AppSearchSession.getFeatures(). Si une fonctionnalité requise n'est pas compatible, l'opération échoue avec une exception. Par exemple, la définition d'un schéma incluant une propriété INDEXING_TYPE_RANGE échoue sur les appareils qui ne sont pas compatibles avec Features.NUMERIC_SEARCH.

Le code suivant vérifie si un AppSearchSession ouvert est compatible avec la recherche numérique :

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

Premiers pas avec AppSearch

L'exemple de cette section montre comment utiliser les API AppSearch pour l'intégration à une application hypothétique de prise de notes.

Écrire une classe de document

La première étape de l'intégration à AppSearch consiste à écrire une classe de document pour décrire les données à insérer dans la base de données. Marquez une classe comme classe de document à l'aide de l'annotation @Document.Vous pouvez utiliser des instances de la classe de document pour placer des documents dans la base de données et les récupérer.

Le code suivant définit une classe de document Note avec un champ annoté @Document.StringProperty pour indexer le texte d'un objet 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;
  }
}

Ouvrir une base de données

Vous devez créer une base de données avant de travailler avec des documents. Le code suivant crée une base de données nommée notes_app et obtient un ListenableFuture pour un AppSearchSession, qui représente la connexion à la base de données et fournit les API pour les opérations de base de données.

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

Définir un schéma

Vous devez définir un schéma avant de pouvoir placer des documents dans la base de données et en récupérer. Le schéma de base de données se compose de différents types de données structurées, appelés "types de schémas". Le code suivant définit le schéma en fournissant la classe de document en tant que type de schéma.

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

Placer un document dans la base de données

Une fois qu'un type de schéma est ajouté, vous pouvez ajouter des documents de ce type à la base de données. Le code suivant crée un document de type de schéma Note à l'aide du compilateur de classe de document Note. Il définit l'espace de noms du document user1 pour représenter un utilisateur arbitraire de cet exemple. Le document est ensuite inséré dans la base de données, et un écouteur est associé pour traiter le résultat de l'opération d'insertion.

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

Vous pouvez rechercher des documents indexés à l'aide des opérations de recherche décrites dans cette section. Le code suivant effectue des requêtes pour le terme "fruit" sur la base de données pour les documents appartenant à l'espace de noms 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);

Itérer sur SearchResults

Les recherches renvoient une instance SearchResults, qui donne accès aux pages des objets SearchResult. Chaque SearchResult contient son GenericDocument correspondant, la forme générale d'un document vers lequel tous les documents sont convertis. Le code suivant récupère la première page des résultats de recherche et convertit le résultat en un document 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);

Supprimer un document

Lorsque l'utilisateur supprime une note, l'application supprime le document Note correspondant de la base de données. Cela garantit que la note n'apparaîtra plus dans les requêtes. Le code suivant envoie une requête explicite pour supprimer le document Note de la base de données par 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);

Persister sur le disque

Les mises à jour d'une base de données doivent être régulièrement conservées sur le disque en appelant requestFlush(). Le code suivant appelle requestFlush() avec un écouteur pour déterminer si l'appel a réussi.

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

Fermer une session

Un AppSearchSession doit être fermé lorsqu'une application n'appelle plus d'opérations de base de données. Le code suivant ferme la session AppSearch qui a été ouverte précédemment et conserve toutes les mises à jour sur le disque.

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

Ressources supplémentaires

Pour en savoir plus sur AppSearch, consultez les ressources supplémentaires suivantes :

Exemples

Envoyer des commentaires

Faites-nous part de vos commentaires et de vos idées via les ressources suivantes :

Issue Tracker

Signalez les bugs pour que nous puissions les corriger.