Как заполнить таблицу базы данных Android Room при первом запуске?
В SQLiteOpenHelper
существует метод onCreate(SQLiteDatabase ...)
, который я использовал для заполнения таблиц базы данных некоторыми исходными данными.
Есть ли способ вставить некоторые данные в таблицу базы данных Room на первом приложение работает?
Ответы
Ответ 1
ПРИМЕЧАНИЕ Пожалуйста, используйте ответ Арнава Рао.
Решение будет заключаться в реализации "SharedPreferences", который входит в состав Android.
Следующий код основан на решении из: Проверьте, запущено ли приложение при первом запуске
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();
}
...
}
}
Ответ 2
Вы можете запускать сценарии после создания базы данных или запускать каждый раз, когда база данных открывается с помощью RoomDatabase.Callback
, этот класс доступен в последней версии библиотеки Room.
Вам необходимо реализовать onCreate
и onOpen
для RoomDatabase.Callback
и добавить его в RoomDatabase.Builder
как показано ниже.
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
}
};
Ссылка
Вы можете использовать Room DAO в методах RoomDatabase.Callback для заполнения базы данных. Для полных примеров см. Pagination и 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);
}
});
}
};
Ответ 3
Я попытался использовать RoomDatabase.Callback в соответствии с предложением Арнава Рао, но для использования обратного вызова нельзя использовать DAO, поскольку обратный вызов создается до того, как база данных была построена. Вы можете использовать db.insert и значения содержимого, но я не думаю, что это было бы правильно. Поэтому, посмотрев немного больше, я потратил целую вечность, но на самом деле я нашел ответ, просматривая примеры, предоставленные Google.
https://github.com/googlesamples/android-architecture-components/blob/master/PersistenceContentProviderSample/app/src/main/java/com/example/android/contentprovidersample/data/SampleDatabase.java
См. строку 52, а метод - строку 71. Там, где вы можете увидеть после сборки экземпляра базы данных, следующая строка вызывает метод, который проверяет, есть ли какие-либо записи в базе данных (используя DAO), а затем очищает ли его вставляет исходные данные (снова используя DAO).
Надеюсь, это поможет всем, кто застрял :)
Ответ 4
Я попробовал несколько способов сделать это, каждый из которых недоступен.
Во-первых, я попытался добавить реализацию Migration в комнату с помощью метода addMigrations, но обнаружил, что он работает только во время обновления базы данных, но не при создании.
Затем я попытался передать реализацию SQLiteOpenHelper в Room с помощью метода openHelperFactory. Но после создания кучи классов, чтобы обойти модификаторы доступа на уровне пакетов на уровне пакетов, я отказался от этих усилий. Я также попытался подклассифицировать Room FrameworkSQLiteOpenHelperFactory, но, опять же, модификатор доступа на уровне пакета его конструктора не поддерживал это.
Наконец, я создал IntentService для заполнения данных и вызвал их из метода onCreate моего подкласса Application. Подход работает, но лучшим решением должно стать предстоящее исправление проблемы трекера, упомянутой Sinigami в другом месте на этой странице.
Дэррил
[Добавлено 19 июля 2017 года]
Проблема выглядит так, как если бы она разрешилась в Room 1.0.0. Alpha 5. В этом выпуске добавлен обратный вызов в RoomDatabase, который позволяет выполнять код при создании базы данных. Взгляните на:
https://developer.android.com/reference/android/arch/persistence/room/RoomDatabase.Callback.html
Ответ 5
@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();
}
Ответ 6
Вы можете заполнить таблицы после создания базы данных, убедитесь, что операция выполняется в отдельном потоке. Вы можете следить за классами ниже, чтобы предварительно заполнить таблицы в первый раз.
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")
)
}
}
}