Salvare i dati in un database locale utilizzando Room Parte di Android Jetpack.

Le app che gestiscono quantità di dati strutturati non banali possono trarre un grande vantaggio di conservare i dati localmente. Il caso d'uso più comune è memorizzare nella cache dati in modo che, quando il dispositivo non può accedere alla rete, l'utente può possono comunque sfogliare quei contenuti quando sono offline.

La libreria di persistenza della stanza fornisce un livello di astrazione rispetto a SQLite per consentire un accesso ottimale al database sfruttando al contempo la piena potenza di SQLite. In particolare, La stanza virtuale offre i seguenti vantaggi:

  • Verifica in fase di compilazione delle query SQL.
  • Annotazioni pratiche che riducono al minimo il boilerplate ripetitivo e soggetto a errori le API nel tuo codice.
  • Percorsi di migrazione dei database semplificati.

Per queste considerazioni, ti consigliamo vivamente di usare la stanza virtuale dell'utilizzo diretto delle API SQLite.

Configura

Per utilizzare Room nella tua app, aggiungi le seguenti dipendenze File build.gradle:

Alla moda

dependencies {
    def room_version = "2.6.1"

    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"

    // To use Kotlin annotation processing tool (kapt)
    kapt "androidx.room:room-compiler:$room_version"
    // To use Kotlin Symbol Processing (KSP)
    ksp "androidx.room:room-compiler:$room_version"

    // optional - RxJava2 support for Room
    implementation "androidx.room:room-rxjava2:$room_version"

    // optional - RxJava3 support for Room
    implementation "androidx.room:room-rxjava3:$room_version"

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "androidx.room:room-guava:$room_version"

    // optional - Test helpers
    testImplementation "androidx.room:room-testing:$room_version"

    // optional - Paging 3 Integration
    implementation "androidx.room:room-paging:$room_version"
}

Kotlin

dependencies {
    val room_version = "2.6.1"

    implementation("androidx.room:room-runtime:$room_version")
    annotationProcessor("androidx.room:room-compiler:$room_version")

    // To use Kotlin annotation processing tool (kapt)
    kapt("androidx.room:room-compiler:$room_version")
    // To use Kotlin Symbol Processing (KSP)
    ksp("androidx.room:room-compiler:$room_version")

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation("androidx.room:room-ktx:$room_version")

    // optional - RxJava2 support for Room
    implementation("androidx.room:room-rxjava2:$room_version")

    // optional - RxJava3 support for Room
    implementation("androidx.room:room-rxjava3:$room_version")

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation("androidx.room:room-guava:$room_version")

    // optional - Test helpers
    testImplementation("androidx.room:room-testing:$room_version")

    // optional - Paging 3 Integration
    implementation("androidx.room:room-paging:$room_version")
}

Componenti principali

Nella stanza virtuale ci sono tre componenti principali:

  • La classe di database che contiene la classe e funge da punto di accesso principale per la connessione sottostante i dati persistenti dell'app.
  • Entità di dati che rappresentano disponibili nel database della tua app.
  • Oggetti di accesso ai dati (DAO) che Fornire metodi che la tua app può utilizzare per eseguire query, aggiornare, inserire ed eliminare presenti nel database.

La classe di database fornisce alla tua app istanze dei DAO associati a del database. A sua volta, l'app può utilizzare i DAO per recuperare i dati come istanze degli oggetti entità dati associati. L'app può anche utilizzare le entità di dati definite per aggiornare le righe delle tabelle corrispondenti; oppure per creare nuove righe da inserire. La Figura 1 illustra la relazione tra i diversi componenti di Room.

Figura 1. Diagramma dell'architettura della biblioteca della stanza.

Esempio di implementazione

Questa sezione presenta un esempio di implementazione di un database Room con un singolo l'entità dati e un singolo DAO.

Entità dati

Il seguente codice definisce un'entità dati User. Ogni istanza di User rappresenta una riga in una tabella user nel database dell'app.

Kotlin

@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)

Java

@Entity
public class User {
    @PrimaryKey
    public int uid;

    @ColumnInfo(name = "first_name")
    public String firstName;

    @ColumnInfo(name = "last_name")
    public String lastName;
}

Per scoprire di più sulle entità dei dati in Stanza, consulta Definire i dati utilizzando Room Entità.

Oggetto di accesso ai dati (DAO)

Il seguente codice definisce un DAO chiamato UserDao. UserDao fornisce il parametro utilizzati dal resto dell'app per interagire con i dati nella tabella user.

Kotlin

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getAll(): List<User>

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List<User>

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
           "last_name LIKE :last LIMIT 1")
    fun findByName(first: String, last: String): User

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}

Java

@Dao
public interface UserDao {
    @Query("SELECT * FROM user")
    List<User> getAll();

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    List<User> loadAllByIds(int[] userIds);

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
           "last_name LIKE :last LIMIT 1")
    User findByName(String first, String last);

    @Insert
    void insertAll(User... users);

    @Delete
    void delete(User user);
}

Per scoprire di più sui DAO, consulta Accesso ai dati utilizzando la stanza virtuale DAO.

Database

Il codice seguente definisce una classe AppDatabase in cui contenere il database. AppDatabase definisce la configurazione del database e funge da risorsa principale dell'app ai dati persistenti. La classe di database deve soddisfare le seguenti condizioni:

  • La classe deve essere annotata con un @Database annotazione che include un entities che elenca tutte le entità di dati associate al database.
  • La classe deve essere una classe astratta che si estende RoomDatabase
  • Per ogni classe DAO associata al database, la classe del database deve definire un metodo astratto che non abbia argomenti e che restituisca un'istanza della classe DAO.

Kotlin

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

Java

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}

Nota: se l'app viene eseguita in un unico processo, devi seguire le istruzioni singleton design pattern durante la creazione di un'istanza di AppDatabase . Ogni istanza RoomDatabase è piuttosto costosa e potresti raramente hanno bisogno di accedere a più istanze all'interno di un singolo processo.

Se l'app viene eseguita in più processi, includi enableMultiInstanceInvalidation() nel generatore di database invocazione. In questo modo, quando hai un'istanza di AppDatabase in ogni processo, puoi invalidare il file del database condiviso in un unico processo, e questa invalidazione si propaga automaticamente alle istanze AppDatabase all'interno di altri processi.

Utilizzo

Dopo aver definito l'entità dati, il DAO e l'oggetto di database, puoi usare il codice seguente per creare un'istanza del database:

Kotlin

val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "database-name"
        ).build()

Java

AppDatabase db = Room.databaseBuilder(getApplicationContext(),
        AppDatabase.class, "database-name").build();

Puoi quindi utilizzare i metodi astratti di AppDatabase per ottenere un'istanza del DAO. A loro volta, puoi utilizzare i metodi dell'istanza DAO per interagire con il database:

Kotlin

val userDao = db.userDao()
val users: List<User> = userDao.getAll()

Java

UserDao userDao = db.userDao();
List<User> users = userDao.getAll();

Risorse aggiuntive

Per saperne di più su Room, consulta le seguenti risorse aggiuntive:

Campioni

Codelab

Blog