Precompila il database delle stanze virtuali

A volte potresti voler iniziare con un database dell'app già creato, vengono caricati con un set specifico di dati. Questa operazione è chiamata precompilazione di un database. Nella stanza 2.2.0 e successive, puoi usare i metodi API per precompilare un database della stanza durante l'inizializzazione con i contenuti di un file di database predefinito file system in-app.

Inserisci automaticamente un asset per app

Per precompilare un database di stanze da un file di database predefinito che si trova in qualsiasi punto della directory assets/ della tua app, chiama createFromAsset() dall'oggetto RoomDatabase.Builder prima di chiamare build():

Kotlin

Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .build()

Java

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .build();

Il metodo createFromAsset() accetta un argomento stringa che contiene un percorso relativo dalla directory assets/ al file del database predefinito.

Precompila dal file system

Per precompilare un database di stanze da un file di database predefinito che si trova in qualsiasi punto del file system del dispositivo ad eccezione della directory assets/ dell'app, chiama il metodo createFromFile() dall'oggetto RoomDatabase.Builder prima di chiamare build():

Kotlin

Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromFile(File("mypath"))
    .build()

Java

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromFile(new File("mypath"))
    .build();

Il metodo createFromFile() accetta un argomento File per il parametro un file di database predefinito. La stanza virtuale crea una copia del file designato anziché piuttosto che aprirla direttamente, quindi assicurati che l'app disponga delle autorizzazioni di lettura .

Gestire le migrazioni che includono database predefiniti

I file di database predefiniti possono anche modificare il modo in cui viene gestito il database delle stanze delle migrazioni di riserva. Solitamente, quando vengono abilitate le migrazioni distruttive e la stanza deve eseguire una migrazione senza percorso, la stanza virtuale elimina tutte le tabelle nel database e crea un database vuoto lo schema specificato per la versione di destinazione. Tuttavia, se includi una file di database predefinito con lo stesso numero della versione di destinazione, Room tenta di compilare il database appena ricreato con i contenuti predefinito dopo aver eseguito la migrazione distruttiva.

Per ulteriori informazioni sulle migrazioni dei database delle stanze, consulta Migrazione della stanza o Microsoft SQL Server.

Le seguenti sezioni presentano alcuni esempi pratici di come funziona.

Esempio: migrazione di riserva con un database predefinito

Supponiamo che:

  • La tua app definisce un database delle stanze nella versione 3.
  • L'istanza di database già installata sul dispositivo è in versione 2.
  • Esiste un file di database predefinito nella versione 3.
  • Non è stato implementato alcun percorso di migrazione dalla versione 2 alla versione 3.
  • Le migrazioni distruttive sono abilitate.

Kotlin

// Database class definition declaring version 3.
@Database(version = 3)
abstract class AppDatabase : RoomDatabase() {
    ...
}

// Destructive migrations are enabled and a prepackaged database
// is provided.
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .fallbackToDestructiveMigration()
    .build()

Java

// Database class definition declaring version 3.
@Database(version = 3)
public abstract class AppDatabase extends RoomDatabase {
    ...
}

// Destructive migrations are enabled and a prepackaged database
// is provided.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .fallbackToDestructiveMigration()
    .build();

Ecco cosa succede in questa situazione:

  1. Poiché il database definito nella tua app è alla versione 3 e il database un'istanza già installata sul dispositivo è in versione 2, necessaria.
  2. Poiché non è stato implementato alcun piano di migrazione dalla versione 2 alla versione 3, la migrazione è di riserva.
  3. Poiché il metodo di creazione di fallbackToDestructiveMigration() è chiamata, la migrazione di riserva è distruttiva. La stanza virtuale elimina il database installata sul dispositivo.
  4. Poiché esiste un file di database predefinito nella versione 3, Room ricrea il database e lo popola utilizzando i contenuti in un file di database. Se, invece, il file di database predefinito fosse versione 2, Room ricorderà che non corrisponde alla versione di destinazione non lo userebbero nella migrazione di riserva.

Esempio: implementazione della migrazione con un database predefinito

Supponiamo invece che la tua app implementi un percorso di migrazione dalla versione 2 a Versione 3:

Kotlin

// Database class definition declaring version 3.
@Database(version = 3)
abstract class AppDatabase : RoomDatabase() {
    ...
}

// Migration path definition from version 2 to version 3.
val MIGRATION_2_3 = object : Migration(2, 3) {
    override fun migrate(database: SupportSQLiteDatabase) {
        ...
    }
}

// A prepackaged database is provided.
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_2_3)
    .build()

Java

// Database class definition declaring version 3.
@Database(version = 3)
public abstract class AppDatabase extends RoomDatabase {
    ...
}

// Migration path definition from version 2 to version 3.
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        ...
    }
};

// A prepackaged database is provided.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_2_3)
    .build();

Ecco cosa succede in questa situazione:

  1. Poiché il database definito nella tua app è alla versione 3 e il database già installata sul dispositivo è alla versione 2, è necessaria una migrazione.
  2. Poiché esiste un percorso di migrazione implementato dalla versione 2 alla versione 3, La stanza virtuale esegue il metodo migrate() definito per aggiornare il database sul dispositivo alla versione 3, conservando i dati già presenti del database. La stanza virtuale non utilizza il file di database predefinito, utilizza file di database predefiniti solo in caso di migrazione di riserva.

Esempio: migrazione in più passaggi con un database predefinito

I file di database predefiniti possono influire anche sulle migrazioni costituite da più passaggi. Considera il seguente caso:

  • La tua app definisce un database delle stanze nella versione 4.
  • L'istanza di database già installata sul dispositivo è in versione 2.
  • Esiste un file di database predefinito nella versione 3.
  • È già stato implementato un percorso di migrazione dalla versione 3 alla versione 4, ma dalla versione 2 alla versione 3.
  • Le migrazioni distruttive sono abilitate.

Kotlin

// Database class definition declaring version 4.
@Database(version = 4)
abstract class AppDatabase : RoomDatabase() {
    ...
}

// Migration path definition from version 3 to version 4.
val MIGRATION_3_4 = object : Migration(3, 4) {
    override fun migrate(database: SupportSQLiteDatabase) {
        ...
    }
}

// Destructive migrations are enabled and a prepackaged database is
// provided.
Room.databaseBuilder(appContext, AppDatabase::class.java, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_3_4)
    .fallbackToDestructiveMigration()
    .build()

Java

// Database class definition declaring version 4.
@Database(version = 4)
public abstract class AppDatabase extends RoomDatabase {
    ...
}

// Migration path definition from version 3 to version 4.
static final Migration MIGRATION_3_4 = new Migration(3, 4) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        ...
    }
};

// Destructive migrations are enabled and a prepackaged database is
// provided.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .addMigrations(MIGRATION_3_4)
    .fallbackToDestructiveMigration()
    .build();

Ecco cosa succede in questa situazione:

  1. Poiché il database definito nella tua app è alla versione 4 e il database un'istanza già installata sul dispositivo è in versione 2, necessaria.
  2. Poiché non è stato implementato alcun percorso di migrazione dalla versione 2 alla versione 3, la migrazione è di riserva.
  3. Poiché il metodo di creazione di fallbackToDestructiveMigration() è chiamata, la migrazione di riserva è distruttiva. La stanza virtuale elimina il database sul dispositivo.
  4. Poiché esiste un file di database predefinito nella versione 3, Room ricrea il database e lo popola utilizzando i contenuti in un file di database.
  5. La versione del database installata sul dispositivo è ora 3. Poiché si tratta di inferiore rispetto a quella definita nell'app, viene eseguita un'altra migrazione necessaria.
  6. Poiché esiste un percorso di migrazione implementato dalla versione 3 alla versione 4, La stanza virtuale esegue il metodo migrate() definito per aggiornare il database sul dispositivo alla versione 4, conservando i dati copiati dal file del database predefinito della versione 3.

Risorse aggiuntive

Per scoprire di più sulla precompilazione di un database delle stanze, consulta le Google Cloud.

Video

Blog