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

Prova con Kotlin Multiplatform
Kotlin Multiplatform consente di condividere il livello del database con altre piattaforme. Scopri come configurare e utilizzare Room Database in KMP

Le app che gestiscono quantità non banali di dati strutturati possono trarre grande vantaggio dalla persistenza locale di questi dati. Il caso d'uso più comune è la memorizzazione nella cache di parti di dati pertinenti, in modo che quando il dispositivo non può accedere alla rete, l'utente possa comunque sfogliare i contenuti offline.

La libreria di persistenza Room fornisce un livello di astrazione su SQLite per consentire un accesso fluido al database sfruttando tutta la potenza di SQLite. In particolare, Room offre i seguenti vantaggi:

  • Verifica in fase di compilazione delle query SQL.
  • Annotazioni di convenienza che riducono al minimo il codice boilerplate ripetitivo e soggetto a errori.
  • Percorsi di migrazione del database semplificati.

Per questi motivi, ti consigliamo vivamente di utilizzare Room anziché utilizzare direttamente le API SQLite.

Configura

Per utilizzare Room nella tua app, aggiungi le seguenti dipendenze al file build.gradle dell'app.

Kotlin

dependencies {
    val room_version = "2.7.2"

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

    // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP)
    // See Add the KSP plugin to your project
    ksp("androidx.room:room-compiler:$room_version")

    // If this project only uses Java source, use the Java annotationProcessor
    // No additional plugins are necessary
    annotationProcessor("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")
}

Groovy

dependencies {
    def room_version = "2.7.2"

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

    // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP)
    // See KSP Quickstart to add KSP to your build
    ksp "androidx.room:room-compiler:$room_version"

    // If this project only uses Java source, use the Java annotationProcessor
    // No additional plugins are necessary
    annotationProcessor "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"
}

Componenti principali

Room è composto da tre componenti principali:

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

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

Figura 1. Diagramma dell'architettura della libreria Room.

Esempio di implementazione

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

Entità dati

Il codice seguente definisce un'entità di 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à di dati in Room, consulta la sezione Definire i dati utilizzando le entità di Room.

Data Access Object (DAO)

Il seguente codice definisce un DAO chiamato UserDao. UserDao fornisce i metodi che il resto dell'app utilizza 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 saperne di più sui DAO, consulta Accesso ai dati tramite i DAO di Room.

Database

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

  • La classe deve essere annotata con un'annotazione @Database che include un array entities che elenca tutte le entità di dati associate al database.
  • La classe deve essere una classe astratta che estende RoomDatabase.
  • Per ogni classe DAO associata al database, la classe del database deve definire un metodo astratto che non ha argomenti e restituisce 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 la tua app viene eseguita in un unico processo, devi seguire il pattern di progettazione singleton quando crei un'istanza di un oggetto AppDatabase. Ogni istanza RoomDatabase è piuttosto costosa e raramente è necessario accedere a più istanze all'interno di un singolo processo.

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

Utilizzo

Dopo aver definito l'entità dati, l'oggetto DAO e il database, puoi utilizzare il seguente codice 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 sua 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