Per evitare che le query blocchino l'interfaccia utente, Room non consente l'accesso al database sul thread principale. Questa limitazione significa che devi rendere asincrone le query DAO. La libreria Room include integrazioni con diversi framework per fornire l'esecuzione di query asincrone.
Le query DAO rientrano in tre categorie:
- Query di scrittura una tantum che inseriscono, aggiornano o eliminano i dati nel database.
- Query di lettura una tantum che leggono i dati dal database una sola volta e restituiscono un risultato con l'istantanea del database in quel momento.
- Query di lettura osservabile che leggono i dati dal database ogni volta che le tabelle di database sottostanti cambiano ed emettono nuovi valori per riflettere queste modifiche.
Opzioni di lingua e framework
Room fornisce il supporto per l'integrazione dell'interoperabilità con funzionalità e librerie specifiche per i vari linguaggi. La tabella seguente mostra i tipi di valori restituiti applicabili in base al tipo di query e al framework:
Tipo di query | Funzionalità del linguaggio Kotlin | RxJava | Guava | Jetpack Lifecycle |
---|---|---|---|---|
Scrittura one-shot | Coroutine (suspend ) |
Single<T> , Maybe<T> ,
Completable |
ListenableFuture<T> |
N/D |
Lettura one-shot | Coroutine (suspend ) |
Single<T> , Maybe<T> |
ListenableFuture<T> |
N/D |
Lettura osservabile | Flow<T> |
Flowable<T> , Publisher<T> ,
Observable<T> |
N/D | LiveData<T> |
Questa guida illustra tre possibili modi per utilizzare queste integrazioni per implementare query asincrone nelle tue DAO.
Kotlin con Flow e couroutine
Kotlin fornisce funzionalità di linguaggio che ti consentono di scrivere query asincrone senza framework di terze parti:
- In Room 2.2 e versioni successive, puoi utilizzare la funzionalità Flow di Kotlin per scrivere query osservabili.
- In Room 2.1 e versioni successive, puoi utilizzare la parola chiave
suspend
per rendere asincrone le query DAO utilizzando le coroutine Kotlin.
Java con RxJava
Se la tua app utilizza il linguaggio di programmazione Java, puoi utilizzare tipi di ritorno specializzati del framework RxJava per scrivere metodi DAO asincroni. Room fornisce il supporto per i seguenti tipi di valori restituiti di RxJava 2:
- Per le query una tantum, Room 2.1 e versioni successive supportano i tipi di valori restituiti
Completable
,Single<T>
eMaybe<T>
. - Per le query osservabili, Room supporta i tipi di ritorno
Publisher<T>
,Flowable<T>
eObservable<T>
.
Inoltre, Room 2.3 e versioni successive supportano RxJava 3.
Java con LiveData e Guava
Se la tua app utilizza il linguaggio di programmazione Java e non vuoi utilizzare il framework RxJava, puoi utilizzare le seguenti alternative per scrivere query asincrone:
- Puoi utilizzare la classe wrapper
LiveData
di Jetpack per scrivere query osservabili asincrone. - Puoi utilizzare il wrapper
ListenableFuture<T>
di Guava per scrivere query una tantum asincrone.
Scrivi query una tantum asincrone
Le query una tantum sono operazioni di database che vengono eseguite una sola volta e acquisiscono uno snapshot di dati al momento dell'esecuzione. Ecco alcuni esempi di query una tantum asincrone:
Kotlin
@Dao interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertUsers(vararg users: User) @Update suspend fun updateUsers(vararg users: User) @Delete suspend fun deleteUsers(vararg users: User) @Query("SELECT * FROM user WHERE id = :id") suspend fun loadUserById(id: Int): User @Query("SELECT * from user WHERE region IN (:regions)") suspend fun loadUsersByRegion(regions: List<String>): List<User> }
Java
@Dao public interface UserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) public Completable insertUsers(List<User> users); @Update public Completable updateUsers(List<User> users); @Delete public Completable deleteUsers(List<User> users); @Query("SELECT * FROM user WHERE id = :id") public Single<User> loadUserById(int id); @Query("SELECT * from user WHERE region IN (:regions)") public Single<List<User>> loadUsersByRegion(List<String> regions); }
Java
@Dao public interface UserDao { // Returns the number of users inserted. @Insert(onConflict = OnConflictStrategy.REPLACE) public ListenableFuture<Integer> insertUsers(List<User> users); // Returns the number of users updated. @Update public ListenableFuture<Integer> updateUsers(List<User> users); // Returns the number of users deleted. @Delete public ListenableFuture<Integer> deleteUsers(List<User> users); @Query("SELECT * FROM user WHERE id = :id") public ListenableFuture<User> loadUserById(int id); @Query("SELECT * from user WHERE region IN (:regions)") public ListenableFuture<List<User>> loadUsersByRegion(List<String> regions); }
Scrivi query osservabili
Le query osservabili sono operazioni di lettura che emettono nuovi valori ogni volta che vengono apportate modifiche a una delle tabelle a cui fa riferimento la query. Un modo per utilizzarlo è mantenere aggiornato un elenco visualizzato di elementi man mano che gli elementi nel database sottostante vengono inseriti, aggiornati o rimossi. Ecco alcuni esempi di query osservabili:
Kotlin
@Dao interface UserDao { @Query("SELECT * FROM user WHERE id = :id") fun loadUserById(id: Int): Flow<User> @Query("SELECT * from user WHERE region IN (:regions)") fun loadUsersByRegion(regions: List<String>): Flow<List<User>> }
Java
@Dao public interface UserDao { @Query("SELECT * FROM user WHERE id = :id") public Flowable<User> loadUserById(int id); @Query("SELECT * from user WHERE region IN (:regions)") public Flowable<List<User>> loadUsersByRegion(List<String> regions); }
Java
@Dao public interface UserDao { @Query("SELECT * FROM user WHERE id = :id") public LiveData<User> loadUserById(int id); @Query("SELECT * from user WHERE region IN (:regions)") public LiveData<List<User>> loadUsersByRegion(List<String> regions); }
Risorse aggiuntive
Per scoprire di più sulle query DAO asincrone, consulta le seguenti risorse aggiuntive: