Estoy desarrollando una aplicación con RoomDatabase que necesita rellenar previamente sus datos; Ya logré hacerlo agregando la devolución de llamada onCreate(), pero solo se llama cuando se accede a la base de datos la primera vez (como llamar a una de las funciones de Daos).

¿Hay alguna forma de forzar la creación de la base de datos sin realizar ninguna operación de lectura o escritura?

Ese es mi código, MyDatabase.get() se llama en App.onCreate()

@Database(entities = {Entity1.class, Entity2.class}, version = 1, exportSchema = true)
public abstract class MyDatabase extends RoomDatabase {

    private static MyDatabase sInstance;

    public synchronized static TaxCodeDatabase get(Context context) {
        if (sInstance == null) {
            sInstance = buildDatabase(context);
        }
        return sInstance;
    }

    private static MyCodeDatabase buildDatabase(final Context context) {
        return Room.databaseBuilder(context,
                MyCodeDatabase.class,
                "my-database")
                .addCallback(new Callback() {
                    @Override
                    public void onCreate(@NonNull SupportSQLiteDatabase db) {
                        super.onCreate(db);
                        sInstance.preFillData(context);
                      });
                    }
                })
                .build();
    }

    public abstract Entity1Dao entity2Dao();

    public abstract Entity2Dao entity1Dao();

    /**
     * Populates the database with a series of initial data
     *
     * @param aContext
     */
    public void prePopulateData(Context aContext) {
        //Populate database here
    }
12
Jameido 16 ene. 2018 a las 15:09

3 respuestas

La mejor respuesta

¿Hay alguna forma de forzar la creación de la base de datos sin realizar ninguna operación de lectura o escritura?

No lo siento.

Sin embargo, no hay nada que le impida copiar la base de datos rellenada previamente antes de invocar Room. Debería asegurarse de que la base de datos rellenada previamente contenga los metadatos de Room (por ejemplo, creando esa base de datos utilizando Room).

6
CommonsWare 16 ene. 2018 a las 12:48

Me tomó un tiempo entender por qué una base de datos de Room no se llena con datos iniciales después de invocar .build() en un generador de bases de datos.

En cuanto a mí, es realmente contra-intuitivo que las migraciones y las devoluciones de llamada se desencadenan solo en una operación de lectura / escritura real. En realidad, el problema se debe a que Room utiliza class RoomOpenHelper que, como se menciona en la documentación:

Un asistente abierto que contiene una referencia a la configuración hasta que se abre la base de datos.

Como resultado, la configuración y todas las devoluciones de llamada almacenadas en la instancia de la clase RoomOpenHelper mientras que la Sqlite SQLiteOpenHelper, que realmente realiza migraciones de la base de datos, no se crea (carga de clase diferida en Java).

Para superar este comportamiento, se debe realizar cualquier operación que cause getWritableDatabase(). Terminé con el siguiente enfoque:

RoomDatabase db = Room.databaseBuilder(context,
            ...)
            .build();

  // and then
db.beginTransaction()
db.endTransaction()

  // or query a dummy select statement
db.query("select 1", null)

return db

Después de eso, la base de datos se creará y se completará con los datos iniciales.

18
Maxim 2 jul. 2018 a las 15:03

Abra el explorador de archivos del dispositivo y navegue hasta / data / data / Su aplicación y elimine la carpeta de bases de datos.

0
Jeffrey 20 feb. 2019 a las 02:31