Scrivi query DAO asincrone

Per evitare che le query blocchino l'interfaccia utente, la stanza virtuale non consente l'accesso al database nel thread principale. Questa limitazione significa che devi rendere asincrone le query DAO. La libreria delle stanze include integrazioni con diversi framework per fornire l'esecuzione asincrona delle query.

Le query DAO rientrano in tre categorie:

  • Query di scrittura one-shot che inseriscono, aggiornano o eliminano dati nel database.
  • Query di lettura one-shot che leggono i dati dal database solo una volta e restituiscono un risultato con lo snapshot del database in quel momento.
  • Query di lettura osservabili che leggono i dati dal tuo database ogni volta che le tabelle di database sottostanti cambiano ed emettono nuovi valori per riflettere queste modifiche.

Opzioni relative a linguaggi e framework

Room offre supporto per l'integrazione per l'interoperabilità con funzionalità linguistiche e librerie specifiche. La seguente tabella mostra i tipi restituiti applicabili in base al tipo di query e al framework:

Tipo di query Funzionalità linguistiche di Kotlin RxJava Guava Ciclo di vita jetpack
Scrittura one-shot Coroutine (suspend) Single<T>, Maybe<T> e Completable ListenableFuture<T> N/A
Lettura one-shot Coroutine (suspend) Single<T>, Maybe<T> ListenableFuture<T> N/A
Lettura osservabile Flow<T> Flowable<T>, Publisher<T> e Observable<T> N/A LiveData<T>

Questa guida illustra tre possibili modi in cui puoi utilizzare queste integrazioni per implementare query asincrone nei tuoi DAO.

Kotlin con Flow e couroutines

Kotlin offre funzionalità di linguaggio che consentono di scrivere query asincrone senza framework di terze parti:

  • Nella stanza 2.2 e superiore, puoi utilizzare la funzionalità Flow di Kotlin per scrivere query osservabili.
  • Nella stanza 2.1 e superiore, 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 restituiti specializzati dal framework RxJava per scrivere metodi DAO asincroni. La stanza virtuale fornisce supporto per i seguenti tipi restituiti di RxJava 2:

Inoltre, la stanza virtuale 2.3 e versioni successive supporta 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 one-shot asincrone.

Scrivere query one-shot asincrone

Le query one-shot sono operazioni di database che vengono eseguite una sola volta e acquisiscono uno snapshot dei dati al momento dell'esecuzione. Ecco alcuni esempi di query one-shot 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);
}

Scrivere 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 è aiutarti a 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 saperne di più sulle query DAO asincrone, consulta le seguenti risorse aggiuntive:

Samples

Blog