Scrivi query DAO asincrone

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:

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:

Blog