Merging SQLiteAssetHelper with Room
The General/AssetRoom
sample project demonstrates that latter approach, in the form of AssetSQLiteOpenHelper
and AssetSQLiteOpenHelperFactory
classes.
As with the original SQLiteAssetHelper
, you need to put your pre-populated database in assets/databases/
, under whatever name you want to use for that database:
Then, when creating your RoomDatabase
subclass:
- Use that same database name, and
- Use
openHelperFactory(new AssetSQLiteOpenHelperFactory())
when creating the instance of yourRoomDatabase
viaRoomDatabase.Builder
package com.commonsware.android.room;
import android.arch.persistence.db.framework.AssetSQLiteOpenHelperFactory;
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Database;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.content.Context;
import java.util.List;
@Database(entities={Constant.class}, version=1)
abstract class ConstantsDatabase extends RoomDatabase {
public abstract Constant.Store constantsStore();
static final String DB_NAME="constants.db";
private static volatile ConstantsDatabase INSTANCE=null;
synchronized static ConstantsDatabase get(Context ctxt) {
if (INSTANCE==null) {
INSTANCE=create(ctxt);
}
return(INSTANCE);
}
static ConstantsDatabase create(Context ctxt) {
RoomDatabase.Builder<ConstantsDatabase> b=
Room.databaseBuilder(ctxt.getApplicationContext(), ConstantsDatabase.class,
DB_NAME);
return(b.openHelperFactory(new AssetSQLiteOpenHelperFactory()).build());
}
}
Compared with some of the other Room samples, you will notice that ConstantsDatabase
lacks any option to create an in-memory database. There is a good reason for that: SQLiteAssetHelper
cannot support that, as we have no way of copying the database file into some place where SQLite itself will use it in memory.
This makes testing slightly more aggravating, as you will want to make sure that you delete your database file in an @After
method, as otherwise future runs of your tests will encounter the existing database file:
package com.commonsware.android.room;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4.class)
public class AssetTests {
private ConstantsDatabase db;
private Constant.Store store;
@Before
public void setUp() {
db=ConstantsDatabase.get(InstrumentationRegistry.getTargetContext());
store=db.constantsStore();
}
@After
public void tearDown() {
db.close();
assertTrue(InstrumentationRegistry
.getTargetContext()
.getDatabasePath(ConstantsDatabase.DB_NAME)
.delete());
}
@Test
public void assets() {
assertEquals(13, store.all().size());
store.insert(new Constant("Pi", 3.1415926));
assertEquals(14, store.all().size());
}
}
However, otherwise, using the pre-populated database is no different than using a regular Room database. Whether the data can be modified is up to you, particularly with your @Dao
class — if you do not write any DAO methods that modify the data, you should be safe. Note, though, that Room has its own metadata table, which might be modified by Room as it sees fit.
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.