How to populate the Android Room database table on first start?

In SQLiteOpenHelper there is an onCreate(SQLiteDatabase ...) method that I used to populate the database tables with some raw data.

Is there a way to insert some data into the Room database table on the first application running?

+30
android android room
source share
6 answers

NOTE Please use the answer of Arnava Rao.

The solution will be to implement the "SharedPreferences", which is part of Android.

The following code is based on a solution from: Check if the application is launched on first launch

 public class MyActivity extends Activity { SharedPreferences prefs = null; @Override protected void onCreate(Bundle savedInstanceState) { ... prefs = getSharedPreferences("com.mycompany.myAppName", MODE_PRIVATE); ... } @Override protected void onResume() { ... if (prefs.getBoolean("firstrun", true)) { // !DO YOUR DATABASE INSERT/POPULATION HERE! prefs.edit().putBoolean("firstrun", false).commit(); } ... } } 
-nine
source share

You can run scripts after creating the database or run each time the database is opened using RoomDatabase.Callback , this class is available in the latest version of the Room library.

You need to implement onCreate and onOpen for RoomDatabase.Callback and add it to RoomDatabase.Builder as shown below.

 yourDatabase = Room.databaseBuilder(context, YourDatabase.class, "your db") .addCallback(rdc) .build(); RoomDatabase.Callback rdc = new RoomDatabase.Callback() { public void onCreate (SupportSQLiteDatabase db) { // do something after database has been created } public void onOpen (SupportSQLiteDatabase db) { // do something every time database is open } }; 

Link

You can use Room DAO in RoomDatabase.Callback methods to populate the database. For complete examples, see Pagination and Room example.

  RoomDatabase.Callback dbCallback = new RoomDatabase.Callback() { public void onCreate(SupportSQLiteDatabase db) { Executors.newSingleThreadScheduledExecutor().execute(new Runnable() { @Override public void run() { getYourDB(ctx).yourDAO().insertData(yourDataList); } }); } }; 
+81
source share

I tried using RoomDatabase.Callback as suggested by Arnav Rao, but you cannot use DAO to use the callback, since the callback is created before the database has been built. You can use db.insert and content values, but I don't think that would be correct. Therefore, looking a little more, I spent ages, but in fact I found the answer by looking at the examples provided by Google.

https://github.com/googlesamples/android-architecture-components/blob/master/PersistenceContentProviderSample/app/src/main/java/com/example/android/contentprovidersample/data/SampleDatabase.java

See line 52, and the method is line 71. Where you can see after building the database instance, the next line calls a method that checks to see if there are any records in the database (using DAO) and then cleans it inserts the original data (again using the DAO).

Hope this helps everyone who is stuck :)

+10
source share

I tried several ways to do this, each of which is not available.

First, I tried to add the Migration implementation to the room using the addMigrations method, but found that it only works when updating the database, but not when creating it.

Then I tried to pass the implementation of SQLiteOpenHelper to Room using the openHelperFactory method. But after creating a bunch of classes to get around package-level access modifiers at the package level, I gave up on this effort. I also tried to subclass Room FrameworkSQLiteOpenHelperFactory, but again, the access modifier at the package level of its constructor did not support this.

Finally, I created an IntentService to populate the data and called it from the onCreate method of my Application subclass. The approach works, but the upcoming fix for the tracker issue mentioned by Sinigami elsewhere on this page should be the best solution.

Darryl

[Added July 19, 2017]

The problem looks as if it resolved in Room 1.0.0. Alpha 5. In this release, a callback has been added to RoomDatabase, which allows code to be executed when creating the database. Take a look at:

https://developer.android.com/reference/android/arch/persistence/room/RoomDatabase.Callback.html

+5
source share
 @Provides @Singleton LocalDatabase provideLocalDatabase(@DatabaseInfo String dbName, Context context) { return Room.databaseBuilder(context, LocalDatabase.class, dbName) .addCallback(new RoomDatabase.Callback() { @Override public void onCreate(@NonNull SupportSQLiteDatabase db) { super.onCreate(db); db.execSQL("INSERT INTO id_generator VALUES(1, 1, 1);"); } }) // .addMigrations(LocalDatabase.MIGRATION_1_2) .build(); } 
+1
source share

You can fill in the tables after creating the database, make sure that the operation is performed in a separate thread. You can follow the classes below to pre-populate the tables for the first time.

AppDatabase.kt

 @Database(entities = [User::class], version = 1, exportSchema = false) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao companion object { // For Singleton instantiation @Volatile private var instance: AppDatabase? = null fun getInstance(context: Context): AppDatabase { return instance ?: synchronized(this) { instance ?: buildDatabase(context).also { instance = it } } } private fun buildDatabase(context: Context): AppDatabase { return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME) .addCallback(object : RoomDatabase.Callback() { override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) //pre-populate data Executors.newSingleThreadExecutor().execute { instance?.let { it.userDao().insertUsers(DataGenerator.getUsers()) } } } }) .build() } } } 

DataGenerator.kt

 class DataGenerator { companion object { fun getUsers(): List<User>{ return listOf( User(1, "Noman"), User(2, "Aayan"), User(3, "Tariqul") ) } } } 
0
source share

All Articles