AppSearch to wydajne rozwiązanie do wyszukiwania na urządzeniu, które umożliwia zarządzanie uporządkowanymi danymi przechowywanymi lokalnie. Zawiera interfejsy API do indeksowania i pobierania danych za pomocą wyszukiwania pełnotekstowego. Aplikacje mogą używać AppSearch do oferowania niestandardowych funkcji wyszukiwania w aplikacji, dzięki czemu użytkownicy mogą wyszukiwać treści nawet w trybie offline.
AppSearch oferuje te funkcje:
- szybka implementacja pamięci masowej zoptymalizowana pod kątem urządzeń mobilnych i małego wykorzystania operacji wejścia-wyjścia;
- Bardzo wydajne indeksowanie i wykonywanie zapytań na dużych zbiorach danych.
- obsługę wielu języków, np. angielskiego i hiszpańskiego;
- Ranking trafności i ocena wykorzystania
Dzięki mniejszemu wykorzystaniu operacji wejścia/wyjścia AppSearch zapewnia mniejsze opóźnienia podczas indeksowania i wyszukiwania w dużych zbiorach danych w porównaniu z SQLite. AppSearch upraszcza zapytania dotyczące różnych typów, obsługując pojedyncze zapytania, podczas gdy SQLite scala wyniki scalone z wielu tabel.
Aby zilustrować funkcje AppSearch, weźmy przykład aplikacji muzycznej, która zarządza ulubionymi utworami użytkowników i umożliwia im łatwe wyszukiwanie. Użytkownicy słuchają muzyki z całego świata, a tytuły utworów są w różnych językach. AppSearch natywnie obsługuje indeksowanie i wysyłanie zapytań w tych językach. Gdy użytkownik wyszukuje utwór według tytułu lub nazwy wykonawcy, aplikacja po prostu przekazuje żądanie do AppSearch, aby szybko i skutecznie pobrać pasujące utwory. Aplikacja wyświetla wyniki, dzięki czemu użytkownicy mogą szybko zacząć odtwarzać ulubione utwory.
Konfiguracja
Aby używać AppSearch w aplikacji, dodaj do jej pliku build.gradle te zależności:
Odlotowe
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") }
Pojęcia związane z AppSearch
Poniższy diagram przedstawia pojęcia związane z AppSearch i ich interakcje.
Rysunek 1. Diagram pojęć związanych z AppSearch: baza danych AppSearch, schemat, typy schematów, dokumenty, sesja i wyszukiwanie.
Baza danych i sesja
Baza danych AppSearch to kolekcja dokumentów zgodna ze schematem bazy danych. Aplikacje klienckie tworzą bazę danych, podając kontekst aplikacji i nazwę bazy danych. Bazy danych mogą być otwierane tylko przez aplikację, która je utworzyła. Po otwarciu bazy danych zwracana jest sesja umożliwiająca interakcję z bazą danych. Sesja jest punktem wejścia do wywoływania interfejsów API AppSearch i pozostaje otwarta, dopóki nie zostanie zamknięta przez aplikację kliencką.
Schemat i typy schematów
Schemat reprezentuje strukturę organizacyjną danych w bazie danych AppSearch.
Schemat składa się z typów schematów, które reprezentują unikalne typy danych. Typy schematów składają się z właściwości, które zawierają nazwę, typ danych i liczność. Po dodaniu typu schematu do schematu bazy danych można tworzyć dokumenty tego typu i dodawać je do bazy danych.
Dokumenty
W AppSearch jednostka danych jest reprezentowana jako dokument. Każdy dokument w bazie danych AppSearch jest jednoznacznie identyfikowany przez przestrzeń nazw i identyfikator. Przestrzenie nazw służą do oddzielania danych z różnych źródeł, gdy zapytanie ma dotyczyć tylko jednego źródła, np. kont użytkowników.
Dokumenty zawierają sygnaturę czasową utworzenia, czas życia (TTL) i wynik, który może być używany do rankingu podczas pobierania. Do dokumentu jest też przypisany typ schematu, który opisuje dodatkowe właściwości danych, które musi mieć dokument.
Klasa dokumentu to abstrakcja dokumentu. Zawiera on pola z adnotacjami, które reprezentują zawartość dokumentu. Domyślnie nazwa klasy dokumentu określa nazwę typu schematu.
Szukaj
Dokumenty są indeksowane i można je wyszukiwać, podając zapytanie. Dokument jest dopasowywany i uwzględniany w wynikach wyszukiwania, jeśli zawiera słowa z zapytania lub pasuje do innej specyfikacji wyszukiwania. Wyniki są uporządkowane na podstawie wyniku i strategii rankingu. Wyniki wyszukiwania są reprezentowane przez strony, które można pobierać sekwencyjnie.
AppSearch oferuje dostosowywanie wyszukiwania, np. filtry, konfigurację rozmiaru strony i fragmenty kodu.
pamięć platformy, pamięć lokalna lub pamięć Usług Google Play;
AppSearch oferuje 3 rozwiązania do przechowywania danych: LocalStorage, PlatformStorage i PlayServicesStorage. W przypadku LocalStorage aplikacja zarządza indeksem, który znajduje się w katalogu danych aplikacji. Dzięki PlatformStorage i PlayServicesStorage aplikacja współtworzy centralny indeks całego systemu. Indeks aplikacji PlatformStorage jest hostowany na serwerze systemowym, a indeks aplikacji PlayServicesStorage – w pamięci Usług Google Play. Dostęp do danych w tych indeksach centralnych jest ograniczony do danych, które zostały przesłane przez Twoją aplikację, oraz danych, które zostały wyraźnie udostępnione przez inną aplikację. Wszystkie te opcje pamięci masowej korzystają z tego samego interfejsu API i można je wymieniać w zależności od wersji urządzenia.
Pamiętaj, że obsługa funkcji różni się w zależności od opcji miejsca na dane i urządzenia. Więcej informacji znajdziesz w artykule Sprawdzanie dostępności funkcji.
Ten kod tworzy sesję PlatformStorage na Androidzie 12 (API na poziomie 31) lub nowszym oraz sesję PlayServicesStorage lub LocalStorage we wcześniejszych wersjach:
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())); } }
Dzięki PlatformStorage i PlayServicesStorage Twoja aplikacja może bezpiecznie udostępniać dane innym aplikacjom, aby mogły one również wyszukiwać dane Twojej aplikacji. Udostępnianie danych aplikacji tylko do odczytu jest przyznawane za pomocą uzgadniania certyfikatu, aby upewnić się, że druga aplikacja ma uprawnienia do odczytu danych. Więcej informacji o tym interfejsie API znajdziesz w dokumentacji setSchemaTypeVisibilityForPackage().
Dodatkowo dzięki PlatformStorage zindeksowane dane mogą być wyświetlane na powierzchniach interfejsu systemu. Aplikacje mogą zrezygnować z wyświetlania niektórych lub wszystkich danych w interfejsie systemu. Więcej informacji o tym interfejsie API znajdziesz w dokumentacji setSchemaTypeDisplayedBySystem().
| Funkcje | LocalStorage (zgodna z Androidem 5.0 lub nowszym) |
PlatformStorage (zgodne z Androidem 12 lub nowszym) |
PlayServicesStorage (zgodna z Androidem 5.0 lub nowszym) |
|---|---|---|---|
| efektywne wyszukiwanie pełnotekstowe, | |||
| Obsługa wielu języków | |||
| mniejszy rozmiar pliku binarnego, | |||
| Udostępnianie danych między aplikacjami | |||
| Możliwość wyświetlania danych na platformach interfejsu systemu | |||
| Można indeksować nieograniczoną liczbę dokumentów o dowolnym rozmiarze. | |||
| Szybsze operacje bez dodatkowego czasu oczekiwania na binder |
Wybierając między LocalStorage a PlatformStorage, należy wziąć pod uwagę dodatkowe kompromisy. PlatformStorage opakowuje interfejsy API Jetpacka w usługę systemową AppSearch, więc wpływ na rozmiar pliku APK jest minimalny w porównaniu z użyciem LocalStorage. Oznacza to jednak, że operacje AppSearch powodują dodatkowe opóźnienie binder podczas wywoływania usługi systemowej AppSearch. W przypadku PlatformStorage AppSearch ogranicza liczbę i rozmiar dokumentów, które aplikacja może indeksować, aby zapewnić wydajny indeks centralny. PlayServicesStorage ma też takie same ograniczenia jak PlatformStorage i jest obsługiwany tylko na urządzeniach z usługami Google Play.
Sprawdzanie dostępności funkcji
Chociaż wszystkie opcje pamięci masowej korzystają z tego samego interfejsu API, niektóre funkcje nie są dostępne we wszystkich opcjach pamięci masowej ani na wszystkich urządzeniach. W dokumentacji interfejsu API adnotacja @RequiresFeature identyfikuje interfejsy API, które wymagają jednej z tych funkcji, a klasa Features definiuje stałą dla każdej funkcji. Na przykład:
INDEXING_TYPE_RANGE
wymaga Features.NUMERIC_SEARCH.
W przypadku PlatformStorage obsługa funkcji zależy od wersji Androida na urządzeniu.
Począwszy od Androida 13 (poziom interfejsu API 33), obsługa funkcji zależy też od aktualizacji systemowych Google Play, które otrzymało urządzenie. Na przykład PlatformStorage obsługuje wyszukiwanie numeryczne (Features.NUMERIC_SEARCH), wyszukiwanie dosłowne (Features.VERBATIM_SEARCH) i łączenie (Features.JOIN_SPEC_AND_QUALIFIED_ID) tylko na tych urządzeniach:
- urządzenia z Androidem 14 (poziom API 34) lub nowszym;
- urządzenia z Androidem 13 (poziom interfejsu API 33), które otrzymały wymaganą aktualizację systemową Google Play;
Te funkcje nie są obsługiwane na urządzeniach z Androidem 12 lub Androidem 12L (poziomy interfejsu API 31 i 32).
Maksymalna liczba indeksowanych właściwości w dokumencie również różni się w zależności od urządzenia i opcji miejsca na dane. Aby uzyskać limit w czasie działania, wywołaj getMaxIndexedProperties().
Nie polegaj wyłącznie na wersji Androida, aby określić, czy funkcja jest obsługiwana. Zanim wywołasz interfejs API, który wymaga danej funkcji, sprawdź, czy jest ona obsługiwana, wywołując metodę isFeatureSupported() na obiekcie Features zwracanym przez AppSearchSession.getFeatures(). Jeśli wymagana funkcja nie jest obsługiwana, operacja nie powiedzie się i zostanie zgłoszony wyjątek. Przykładem niepowodzenia jest ustawienie schematu, który zawiera właściwość INDEXING_TYPE_RANGE, na urządzeniach, które nie obsługują Features.NUMERIC_SEARCH.
Poniższy kod sprawdza, czy otwarty AppSearchSession obsługuje wyszukiwanie numeryczne:
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. }
Pierwsze kroki z AppSearch
Przykład w tej sekcji pokazuje, jak używać interfejsów API AppSearch do integracji z hipotetyczną aplikacją do robienia notatek.
Zapisywanie klasy dokumentu
Pierwszym krokiem integracji z AppSearch jest napisanie klasy dokumentu, która opisuje dane do wstawienia do bazy danych. Oznacz klasę jako klasę dokumentu za pomocą adnotacji @Document.Możesz używać instancji klasy dokumentu, aby umieszczać dokumenty w bazie danych i pobierać je z niej.
Poniższy kod definiuje klasę dokumentu Note z polem oznaczonym jako @Document.StringProperty do indeksowania tekstu obiektu 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; } }
Otwieranie bazy danych
Zanim zaczniesz pracować z dokumentami, musisz utworzyć bazę danych. Poniższy kod tworzy nową bazę danych o nazwie notes_app i pobiera ListenableFuture dla AppSearchSession, który reprezentuje połączenie z bazą danych i udostępnia interfejsy API do operacji na bazie danych.
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() );
Ustawianie schematu
Zanim będzie można umieszczać dokumenty w bazie danych i pobierać je z niej, musisz ustawić schemat. Schemat bazy danych składa się z różnych typów uporządkowanych danych, nazywanych „typami schematu”. Poniższy kod ustawia schemat, podając klasę dokumentu jako typ schematu.
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);
Umieszczanie dokumentu w bazie danych
Po dodaniu typu schematu możesz dodawać do bazy danych dokumenty tego typu.
Poniższy kod tworzy dokument typu schematu Note za pomocą kreatora klasy dokumentu Note. Ustawia przestrzeń nazw dokumentu user1, aby reprezentowała dowolnego użytkownika tej próbki. Następnie dokument jest wstawiany do bazy danych i dołączany jest detektor, który przetwarza wynik operacji umieszczania.
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);
Szukaj
Możesz wyszukiwać dokumenty, które są indeksowane, korzystając z operacji wyszukiwania opisanych w tej sekcji. Poniższy kod wyszukuje w bazie danych termin „fruit” w dokumentach należących do przestrzeni nazw 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);
Iterowanie po SearchResults
Wyszukiwania zwracają instancję SearchResults, która zapewnia dostęp do stron obiektów SearchResult. Każdy element SearchResult zawiera dopasowany element GenericDocument, czyli ogólną formę dokumentu, na którą są konwertowane wszystkie dokumenty. Podany niżej kod pobiera pierwszą stronę wyników wyszukiwania i konwertuje wynik z powrotem na dokument 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);
Usuwanie dokumentu
Gdy użytkownik usunie notatkę, aplikacja usunie odpowiedni dokument Note z bazy danych. Dzięki temu notatka nie będzie już wyświetlana w zapytaniach. Poniższy kod wysyła wyraźne żądanie usunięcia dokumentu Note z bazy danych według identyfikatora.
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);
Trwale przechowuj na dysku
Aktualizacje bazy danych powinny być okresowo zapisywane na dysku przez wywołanie metody requestFlush(). Poniższy kod wywołuje metodę requestFlush() z detektorem, aby określić, czy wywołanie się powiodło.
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);
Zamykanie sesji
Obiekt AppSearchSession należy zamknąć, gdy aplikacja nie będzie już wywoływać żadnych operacji na bazie danych. Poniższy kod zamyka otwartą wcześniej sesję AppSearch i zapisuje wszystkie aktualizacje na dysku.
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);
Dodatkowe materiały
Więcej informacji o AppSearch znajdziesz w tych materiałach:
Przykłady
- Przykładowa aplikacja AppSearch na Androida (Kotlin) – aplikacja do robienia notatek, która używa AppSearch do indeksowania notatek użytkownika i umożliwia użytkownikom ich wyszukiwanie.
Prześlij opinię
Podziel się z nami swoją opinią i pomysłami, korzystając z tych materiałów:
Zgłaszaj błędy, abyśmy mogli je naprawić.