web-dev-qa-db-fra.com

Comment utiliser Room Persistence Library avec une base de données préremplie?

J'aimerais utiliser Room avec une base de données pré-remplie, mais je ne comprends pas comment dire à Room où trouver ma base de données.

Je l'ai maintenant mis dans src/main/assets/databases et lorsque je crée l’instance pour la base de données Room, je le crée de cette manière:

Room.databaseBuilder(
    getApplicationContext(),
    AppDatabase.class,
    "justintrain.db"
)
.allowMainThreadQueries()
.build();

De cette façon, je pense qu’elle crée une nouvelle base de données à chaque fois, ou de toute façon, qu’elle n’utilise pas la base de données pré-remplie.

Comment puis-je le trouver pour trouver ma base de données?

57
Alberto Giunta

Voici comment j'ai résolu le problème et comment vous pouvez envoyer votre demande avec une base de données pré-remplie (jusqu'à Room v. Alpha5)

  • placez votre base de données SQLite database_name.db dans le dossier assets/databases

  • prenez les fichiers de ce dépôt et mettez-les dans un paquet nommé i.e. sqlAsset

  • dans votre classe AppDatabase, modifiez le code de création de la base de données de votre pièce en conséquence:

    Room.databaseBuilder(context.getApplicationContext(), 
                         AppDatabase.class, 
                         "database_name.db")
    .openHelperFactory(new AssetSQLiteOpenHelperFactory())
    .allowMainThreadQueries()
    .build();
    

Notez que vous devez utiliser "database_name.db" Et non pas getDatabasePath() ou d'autres méthodes: il suffit juste du nom du fichier.

35
Alberto Giunta

Solution simple sans aucune autre bibliothèque externe.

Room s'appuie sur le code-cadre Android existant pour créer ou ouvrir une base de données. Si vous regardez dans le code source de FrameworkSQLiteOpenHelper (version de la salle de SQLiteOpenHelper, _ appelle en interne SQLiteOpenHelper.getReadableDatabase() et d’autres méthodes, le cas échéant.

La solution la plus simple consiste donc simplement à copier le fichier de base de données du répertoire assets vers mContext.getDatabasePath("my-database.sqlite") avant de créer la base de données avec Room.

Dans votre cas, le code ressemble à ceci:

private final String DB_NAME = "my-database.sqlite";

private MyDatabase buildDatabase(Context context) {
    final File dbFile = context.getDatabasePath(DB_NAME);

    if(!dbFile.exists()) {
        copyDatabaseFile(dbFile.getAbsolutePath());
    }

    return Room.databaseBuilder(context.getApplicationContext(),
        MyDatabase.class, DB_NAME)
        .build();
}

private void copyDatabaseFile(String destinationPath) {
    // code to copy the file from assets/database directory to destinationPath
}

Ce lien contient le code nécessaire pour copier la base de données - lien avec code

19
Nishanth

J'avais le même problème alors j'ai créé une bibliothèque qui fait exactement cela. la réponse acceptée fonctionne, mais je pense qu'il est plus facile d'utiliser une bibliothèque.

AppDatabase db = RoomAsset
    .databaseBuilder(context.getApplicationContext(), AppDatabase.class, "database_name.db")
    .build(); 

Ajoutez-le à votre build.gradle racine à la fin des référentiels:

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}

Ajouter la dépendance

dependencies {
    // ... other dependencies
    implementation 'com.github.humazed:RoomAsset:v1.0'
}

vous pouvez trouver la bibliothèque ici: https://github.com/humazed/RoomAsset

16
humazed

vous copiez simplement assets/databases dans app/databases
et que add addMigrations() dans databaseBuilder
il conservera vos données

0
user6269562

Solution similaire avec une pièce sans utiliser de bibliothèques externes: 1. Copiez votre base de données dans le dossier des actifs. 2. Copiez votre base de données à partir du dossier des actifs.

public class MainActivity extends AppCompatActivity {

public static AppDatabase db;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    copyDatabase(getApplicationContext(), "yourdatabase.db");

    db = Room.databaseBuilder(getApplicationContext(), .class, "yourdatabase.db").allowMainThreadQueries().build();
}

private void copyDatabase(Context context, String databaseName) {
    final File dbPath = context.getDatabasePath(databaseName);

    // If the database already exists, return
    if (dbPath.exists()) {
        Log.d("Activity", "db Path Exists");
        return;
    }

    // Make sure we have a path to the file
    dbPath.getParentFile().mkdirs();

    // Try to copy database file
    try {
        final InputStream inputStream = context.getAssets().open(databaseName);
        final OutputStream output = new FileOutputStream(dbPath);

        byte[] buffer = new byte[8192];
        int length;

        while ((length = inputStream.read(buffer, 0, 8192)) > 0) {
            output.write(buffer, 0, length);
        }

        output.flush();
        output.close();
        inputStream.close();
    }
    catch (IOException e) {
        Log.d("Activity", "Failed to open file", e);
        e.printStackTrace();
    }
}

}

0
dig