AppSearch

AppSearch ist eine leistungsstarke On-Device-Suchlösung für die Verwaltung lokal gespeicherter, strukturierter Daten. Sie enthält APIs zum Indexieren von Daten und zum Abrufen von Daten mithilfe der Volltextsuche. Anwendungen können AppSearch verwenden, um benutzerdefinierte In-App-Suchfunktionen anzubieten, mit denen Nutzer auch offline nach Inhalten suchen können.

Diagramm zur Indexierung und Suche in AppSearch

AppSearch bietet die folgenden Funktionen:

  • Eine schnelle, für Mobilgeräte optimierte Speicherimplementierung mit geringer E/A-Nutzung
  • Hocheffiziente Indexierung und Abfrage großer Datasets
  • Unterstützung mehrerer Sprachen, z. B. Englisch und Spanisch
  • Relevanzranking und Nutzungsbewertung

Aufgrund der geringeren E/A-Nutzung bietet AppSearch im Vergleich zu SQLite eine geringere Latenz für die Indexierung und Suche in großen Datasets. AppSearch vereinfacht typübergreifende Abfragen, da einzelne Abfragen unterstützt werden, während SQLite Ergebnisse aus mehreren Tabellen zusammenführt.

Zur Veranschaulichung der Funktionen von AppSearch nehmen wir das Beispiel einer Musikanwendung, die die Lieblingssongs der Nutzer verwaltet und es ihnen ermöglicht, einfach danach zu suchen. Nutzer hören Musik aus der ganzen Welt mit Songtiteln in verschiedenen Sprachen. AppSearch unterstützt die Indexierung und Abfrage dieser Titel nativ. Wenn der Nutzer nach einem Song anhand des Titels oder des Künstlernamens sucht, übergibt die Anwendung die Anfrage einfach an AppSearch, um passende Songs schnell und effizient abzurufen. Die Anwendung zeigt die Ergebnisse an, sodass Nutzer schnell ihre Lieblingssongs abspielen können.

Einrichtung

Wenn Sie AppSearch in Ihrer Anwendung verwenden möchten, fügen Sie der Datei build.gradle Ihrer Anwendung die folgenden Abhängigkeiten hinzu:

Cool

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

}

AppSearch-Konzepte

Das folgende Diagramm veranschaulicht die AppSearch-Konzepte und ihre Interaktionen.

Diagramm einer Clientanwendung und ihrer Interaktionen mit den folgenden AppSearch-Konzepten: AppSearch-Datenbank, Schema, Schematypen, Dokumente, Sitzung und Suche. Abbildung 1: Diagramm der AppSearch-Konzepte: AppSearch-Datenbank, Schema, Schematypen, Dokumente, Sitzung und Suche.

Datenbank und Sitzung

Eine AppSearch-Datenbank ist eine Sammlung von Dokumenten, die dem Datenbankschema entsprechen. Clientanwendungen erstellen eine Datenbank, indem sie ihren Anwendungskontext und einen Datenbanknamen angeben. Datenbanken können nur von der Anwendung geöffnet werden, von der sie erstellt wurden. Wenn eine Datenbank geöffnet wird, wird eine Sitzung zurückgegeben, um mit der Datenbank zu interagieren. Die Sitzung ist der Einstiegspunkt für den Aufruf der AppSearch APIs und bleibt geöffnet, bis sie von der Clientanwendung geschlossen wird.

Schema und Schematypen

Ein Schema stellt die Organisationsstruktur von Daten in einer AppSearch-Datenbank dar.

Das Schema besteht aus Schematypen, die eindeutige Datentypen darstellen. Schematypen bestehen aus Attributen, die einen Namen, einen Datentyp und eine Kardinalität enthalten. Sobald ein Schematyp dem Datenbankschema hinzugefügt wurde, können Dokumente dieses Schematyps erstellt und der Datenbank hinzugefügt werden.

Dokumente

In AppSearch wird eine Dateneinheit als Dokument dargestellt. Jedes Dokument in einer AppSearch-Datenbank wird durch seinen Namespace und seine ID eindeutig identifiziert. Namespaces werden verwendet, um Daten aus verschiedenen Quellen zu trennen, wenn nur eine Quelle abgefragt werden muss, z. B. Nutzerkonten.

Dokumente enthalten einen Zeitstempel für die Erstellung, eine Gültigkeitsdauer (TTL) und eine Punktzahl, die für das Ranking beim Abrufen verwendet werden kann. Einem Dokument wird auch ein Schematyp zugewiesen, der zusätzliche Datenattribute beschreibt, die das Dokument haben muss.

Eine Dokumentklasse ist eine Abstraktion eines Dokuments. Sie enthält annotierte Felder, die den Inhalt eines Dokuments darstellen. Standardmäßig wird der Name des Schematyps durch den Namen der Dokumentklasse festgelegt.

Dokumente werden indexiert und können über eine Abfrage durchsucht werden. Ein Dokument wird abgeglichen und in die Suchergebnisse aufgenommen, wenn es die Begriffe in der Abfrage enthält oder einer anderen Suchspezifikation entspricht. Die Ergebnisse werden nach ihrer Punktzahl und der Ranking-Strategie sortiert. Suchergebnisse werden durch Seiten dargestellt, die Sie nacheinander abrufen können.

AppSearch bietet Anpassungen für die Suche, z. B. Filter, Konfiguration der Seitengröße und Snippeting.

Plattformspeicher, lokaler Speicher oder Speicher für Google Play-Dienste

AppSearch bietet drei Speicherlösungen: LocalStorage, PlatformStorage und PlayServicesStorage. Mit LocalStorage verwaltet Ihre Anwendung einen anwendungsspezifischen Index, der sich im Datenverzeichnis Ihrer Anwendung befindet. Sowohl mit PlatformStorage als auch mit PlayServicesStorage trägt Ihre Anwendung zu einem systemweiten zentralen Index bei. Der Index von PlatformStorage wird auf dem Systemserver gehostet und der Index von PlayServicesStorage im Speicher der Google Play-Dienste. Der Datenzugriff innerhalb dieser zentralen Indexe ist auf Daten beschränkt, die Ihre Anwendung beigetragen hat, und auf Daten, die von einer anderen Anwendung explizit für Sie freigegeben wurden. Alle diese Speicheroptionen verwenden dieselbe API und können je nach Geräteversion ausgetauscht werden.

Die Unterstützung von Funktionen variiert je nach Speicheroption und Gerät. Weitere Informationen finden Sie unter Verfügbarkeit von Funktionen prüfen.

Mit dem folgenden Code wird eine PlatformStorage-Sitzung unter Android 12 (API-Level 31) und höher sowie eine PlayServicesStorage- oder LocalStorage-Sitzung unter früheren Versionen erstellt:

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

Mit PlatformStorage und PlayServicesStorage kann Ihre Anwendung Daten sicher mit anderen Anwendungen teilen, damit diese auch die Daten Ihrer Anwendung durchsuchen können. Die Freigabe von schreibgeschützten Anwendungsdaten wird über einen Zertifikat-Handshake gewährt, um sicherzustellen, dass die andere Anwendung die Berechtigung zum Lesen der Daten hat. Weitere Informationen zu dieser API finden Sie in der Dokumentation zu setSchemaTypeVisibilityForPackage().

Außerdem können mit PlatformStorage indexierte Daten auf System-UI-Oberflächen angezeigt werden. Anwendungen können festlegen, dass einige oder alle ihrer Daten nicht auf System-UI-Oberflächen angezeigt werden. Weitere Informationen zu dieser API finden Sie in der Dokumentation zu setSchemaTypeDisplayedBySystem().

Features LocalStorage (kompatibel mit Android 5.0 und höher) PlatformStorage (kompatibel mit Android 12 und höher) PlayServicesStorage (kompatibel mit Android 5.0 oder höher)
Effiziente Volltextsuche
Unterstützung mehrerer Sprachen
Reduzierte Binärgröße
Datenweitergabe zwischen Anwendungen
Fähigkeit, Daten auf Oberflächen der System-UI anzuzeigen
Unbegrenzte Dokumentgröße und -anzahl können indexiert werden
Schnellere Vorgänge ohne zusätzliche Binder-Latenz

Bei der Wahl zwischen LocalStorage und PlatformStorage sind weitere Vor- und Nachteile zu berücksichtigen. Da PlatformStorage Jetpack APIs über den AppSearch-Systemdienst umschließt, ist die Auswirkung auf die APK-Größe im Vergleich zur Verwendung von LocalStorage minimal. Das bedeutet jedoch auch, dass bei AppSearch-Vorgängen zusätzliche Binder-Latenz entsteht, wenn der AppSearch-Systemdienst aufgerufen wird. Mit PlatformStorage begrenzt AppSearch die Anzahl und Größe der Dokumente, die eine Anwendung indexieren kann, um einen effizienten zentralen Index zu gewährleisten. PlayServicesStorage hat außerdem dieselben Einschränkungen wie PlatformStorage und wird nur auf Geräten mit Google Play-Diensten unterstützt.

Verfügbarkeit von Funktionen überprüfen

Obwohl alle Speicheroptionen dieselbe API verwenden, sind einige Funktionen nicht mit jeder Speicheroption oder auf jedem Gerät verfügbar. In der API-Referenz werden APIs, für die eines dieser Features erforderlich ist, mit der Annotation @RequiresFeature gekennzeichnet. Die Klasse Features definiert für jedes Feature eine Konstante. Beispiel: INDEXING_TYPE_RANGE erfordert Features.NUMERIC_SEARCH.

Bei PlatformStorage hängt die Unterstützung von Funktionen von der Android-Version des Geräts ab. Ab Android 13 (API-Level 33) hängt die Unterstützung von Funktionen auch von den Google Play-Systemupdates ab, die das Gerät erhalten hat. PlatformStorage unterstützt beispielsweise die numerische Suche (Features.NUMERIC_SEARCH), die wortgetreue Suche (Features.VERBATIM_SEARCH) und Joins (Features.JOIN_SPEC_AND_QUALIFIED_ID) nur auf den folgenden Geräten:

  • Geräte mit Android 14 (API-Level 34) oder höher
  • Geräte mit Android 13 (API-Level 33), die das erforderliche Google Play-Systemupdate erhalten haben.

Diese Funktionen werden auf Geräten mit Android 12 oder Android 12L (API-Level 31 und 32) nicht unterstützt.

Die maximale Anzahl indexierter Attribute in einem Dokument variiert ebenfalls je nach Gerät und Speicheroption. Rufen Sie getMaxIndexedProperties() auf, um das Limit zur Laufzeit abzurufen.

Verlassen Sie sich nicht nur auf die Android-Version, um die Unterstützung von Funktionen zu bestimmen. Bevor Sie eine API aufrufen, die ein Feature erfordert, prüfen Sie, ob das Feature unterstützt wird. Rufen Sie dazu isFeatureSupported() für das Features-Objekt auf, das von AppSearchSession.getFeatures() zurückgegeben wird. Wenn ein erforderliches Feature nicht unterstützt wird, schlägt der Vorgang mit einer Ausnahme fehl. Ein Beispiel für einen Fehlerfall ist das Festlegen eines Schemas, das ein INDEXING_TYPE_RANGE-Attribut enthält, das auf Geräten, die Features.NUMERIC_SEARCH nicht unterstützen, fehlschlägt.

Mit dem folgenden Code wird geprüft, ob ein geöffneter AppSearchSession die numerische Suche unterstützt:

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

Erste Schritte mit AppSearch

Das Beispiel in diesem Abschnitt zeigt, wie Sie AppSearch APIs in eine hypothetische Notizen-App einbinden.

Dokumentklasse schreiben

Der erste Schritt zur Einbindung in AppSearch besteht darin, eine Dokumentklasse zu schreiben, um die Daten zu beschreiben, die in die Datenbank eingefügt werden sollen. Markieren Sie eine Klasse mit der Annotation @Document als Dokumentklasse.Sie können Instanzen der Dokumentklasse verwenden, um Dokumente in die Datenbank einzufügen und daraus abzurufen.

Im folgenden Code wird eine Dokumentklasse „Note“ mit einem mit @Document.StringProperty annotierten Feld zum Indexieren des Texts eines Note-Objekts definiert.

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

Datenbank öffnen

Sie müssen eine Datenbank erstellen, bevor Sie mit Dokumenten arbeiten können. Mit dem folgenden Code wird eine neue Datenbank mit dem Namen notes_app erstellt und ein ListenableFuture für ein AppSearchSession abgerufen, das die Verbindung zur Datenbank darstellt und die APIs für Datenbankvorgänge bereitstellt.

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

Schema festlegen

Sie müssen ein Schema festlegen, bevor Sie Dokumente in die Datenbank einfügen und daraus abrufen können. Das Datenbankschema besteht aus verschiedenen Arten strukturierter Daten, die als „Schematypen“ bezeichnet werden. Im folgenden Code wird das Schema festgelegt, indem die Dokumentklasse als Schematyp angegeben wird.

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

Dokument in die Datenbank einfügen

Nachdem ein Schematyp hinzugefügt wurde, können Sie der Datenbank Dokumente dieses Typs hinzufügen. Mit dem folgenden Code wird ein Dokument des Schematyps Note mithilfe des Dokumentklassen-Builders Note erstellt. Der Dokument-Namespace user1 wird so festgelegt, dass er einen beliebigen Nutzer dieses Beispiels darstellt. Das Dokument wird dann in die Datenbank eingefügt und ein Listener wird angehängt, um das Ergebnis des Put-Vorgangs zu verarbeiten.

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

Sie können indexierte Dokumente mit den in diesem Abschnitt beschriebenen Suchvorgängen durchsuchen. Mit dem folgenden Code werden Abfragen für den Begriff „fruit“ in der Datenbank nach Dokumenten ausgeführt, die zum Namespace user1 gehören.

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

SearchResults durchlaufen

Suchanfragen geben eine SearchResults-Instanz zurück, die Zugriff auf die Seiten von SearchResult-Objekten bietet. Jedes SearchResult enthält das entsprechende GenericDocument, die allgemeine Form eines Dokuments, in die alle Dokumente konvertiert werden. Mit dem folgenden Code wird die erste Seite der Suchergebnisse abgerufen und das Ergebnis wieder in ein Note-Dokument konvertiert.

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

Dokument entfernen

Wenn der Nutzer eine Notiz löscht, löscht die Anwendung das entsprechende Note-Dokument aus der Datenbank. So wird die Notiz nicht mehr in Abfragen angezeigt. Mit dem folgenden Code wird eine explizite Anfrage zum Entfernen des Dokuments Note aus der Datenbank nach ID gestellt.

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

Auf Laufwerk beibehalten

Aktualisierungen einer Datenbank sollten regelmäßig durch Aufrufen von requestFlush() auf dem Laufwerk gespeichert werden. Im folgenden Code wird requestFlush() mit einem Listener aufgerufen, um festzustellen, ob der Aufruf erfolgreich war.

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

Sitzung schließen

Eine AppSearchSession sollte geschlossen werden, wenn eine Anwendung keine Datenbankvorgänge mehr aufruft. Mit dem folgenden Code wird die zuvor geöffnete AppSearch-Sitzung geschlossen und alle Aktualisierungen werden auf dem Laufwerk gespeichert.

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

Zusätzliche Ressourcen

Weitere Informationen zu AppSearch finden Sie in den folgenden zusätzlichen Ressourcen:

Beispiele

  • Android AppSearch-Beispiel (Kotlin): Eine Notizen-App, die AppSearch verwendet, um die Notizen eines Nutzers zu indexieren und ihm die Suche in seinen Notizen zu ermöglichen.

Feedback geben

Über die folgenden Ressourcen können Sie uns Ihr Feedback und Ihre Ideen mitteilen:

Issue Tracker

Melden Sie Fehler, damit wir sie beheben können.