Écrire des requêtes DAO asynchrones

Pour empêcher les requêtes de bloquer l'interface utilisateur, Room n'autorise pas l'accès à la base de données sur le thread principal. Cette restriction signifie que vous devez rendre vos requêtes DAO asynchrones. La bibliothèque Room inclut des intégrations avec différents frameworks pour permettre l'exécution de requêtes asynchrones.

Les requêtes DAO appartiennent à trois catégories :

  • Requêtes d'écriture unique qui insèrent, mettent à jour ou suppriment des données dans la base de données.
  • Requêtes de lecture unique qui lisent les données de votre base de données une seule fois et renvoient un résultat avec l'instantané de la base de données à ce moment-là.
  • Requêtes de lecture observables qui lisent les données de votre base de données chaque fois que les tables de base de données sous-jacentes changent et émettent de nouvelles valeurs reflétant ces modifications.

Options de langage et de framework

Room permet l'interopérabilité avec des bibliothèques et des fonctionnalités de langage spécifiques. Le tableau suivant présente les types renvoyés applicables en fonction du type de requête et du framework :

Type de requête Fonctionnalités du langage Kotlin RxJava Guava Jetpack Lifecycle
Écriture unique Coroutines (suspend) Single<T>, Maybe<T>, Completable ListenableFuture<T> N/A
Lecture unique Coroutines (suspend) Single<T>, Maybe<T> ListenableFuture<T> N/A
Lecture observable Flow<T> Flowable<T>, Publisher<T>, Observable<T> N/A LiveData<T>

Ce guide présente trois façons d'utiliser ces intégrations pour implémenter des requêtes asynchrones dans vos DAO.

Kotlin avec Flow et coroutines

Kotlin fournit des fonctionnalités de langage qui vous permettent d'écrire des requêtes asynchrones sans frameworks tiers :

  • Dans Room 2.2 et les versions ultérieures, vous pouvez utiliser la fonctionnalité Flow de Kotlin pour écrire des requêtes observables.
  • Dans Room 2.1 et les versions ultérieures, vous pouvez utiliser le mot clé suspend pour rendre vos requêtes DAO asynchrones à l'aide de coroutines Kotlin.

Java avec RxJava

Si votre application utilise le langage de programmation Java, vous pouvez utiliser des types renvoyés spécialisés du framework RxJava pour écrire des méthodes DAO asynchrones. Room est compatible avec les types renvoyés RxJava 2 suivants :

De plus, la version 2.3 et les versions ultérieures sont compatibles avec RxJava 3.

Java avec LiveData et Guava

Si votre application utilise le langage de programmation Java et que vous ne souhaitez pas utiliser le framework RxJava, vous pouvez utiliser les alternatives suivantes pour écrire des requêtes asynchrones :

  • Vous pouvez utiliser la classe wrapper LiveData de Jetpack pour écrire des requêtes observables asynchrones.
  • Vous pouvez utiliser le wrapper ListenableFuture<T> de Guava pour écrire des requêtes uniques asynchrones.

Écrire des requêtes uniques asynchrones

Les requêtes uniques sont des opérations de base de données qui ne s'exécutent qu'une seule fois et récupèrent un instantané des données au moment de l'exécution. Voici quelques exemples de requêtes uniques asynchrones :

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

Écrire des requêtes observables

Les requêtes observables sont des opérations de lecture qui émettent de nouvelles valeurs en cas de modification de l'une des tables référencées par la requête. Vous pouvez les utiliser, par exemple, pour maintenir à jour la liste des éléments affichés à mesure que les éléments de la base de données sous-jacentes sont insérés, mis à jour ou supprimés. Voici quelques exemples de requêtes observables :

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

Ressources supplémentaires

Pour en savoir plus sur les requêtes DAO asynchrones, consultez les ressources supplémentaires suivantes :

Blogs