Android Room заполняет базу данных новыми данными после миграции?

Я уже опубликовал приложение в Play Store, которое предварительно заполняет базу данных Room данными в обратном вызове onCreate. Данные считываются из файла JSON и помещаются в базу данных. Все работает для данных в базу данных (добавляйте новые записи в таблицу) снова из файла JSON.

Вот мой метод RoomDatabase create:

private fun create(context: Context): MyDatabase {
        val MIGRATION_1_2 = object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL("ALTER TABLE dogs ADD COLUMN language TEXT")
            }
        }
        return Room.databaseBuilder(
            context.applicationContext,
            MyDatabase::class.java,
            DB_NAME
        )
            .addMigrations(MIGRATION_1_2)
            // prepopulate the database after onCreate was called
            .addCallback(object : RoomDatabase.Callback() {
                override fun onCreate(db: SupportSQLiteDatabase) {
                    super.onCreate(db)
                    GlobalScope.launch {
                        getInstance(context)?.let { DatabaseUtils.prepopulateDatabase(context, it) }
                    }
                }
            })
            .build()
    }

Есть ли простой способ сделать это без написания сотен SQL-запросов вручную? Или, если есть способ, как удалить всю базу данных и создать новую с совершенно новыми данными, возможно, это тоже будет для меня вариантом.

Заранее спасибо ребята ;)


person MrVasilev    schedule 16.07.2019    source источник


Ответы (2)


Вы можете удалить/очистить предыдущую базу данных, используя fallbackToDestructiveMigration.

database = Room.databaseBuilder(context.getApplicationContext(),
                    UsersDatabase.class, "Sample.db")
            .fallbackToDestructiveMigration()
            .build();

См. сценарий 3 из этой статьи Google Понимание миграции с помощью Room

person TheAnkush    schedule 17.07.2019
comment
Но сценарий 3 из этой статьи говорит: Итак, теперь наше приложение не падает, но мы теряем все данные. Поэтому убедитесь, что именно так вы специально хотите обрабатывать миграции. Означает ли это, что база данных будет пустой или она будет воссоздана, и при первом доступе снова будет вызван обратный вызов onCreate, и база данных будет снова предварительно заполнена с помощью новые данные? - person MrVasilev; 17.07.2019
comment
@MrVasilev - он будет очищен и не будет предварительно заполнен. Как насчет того, чтобы дать ему тест?? - person TheAnkush; 17.07.2019
comment
Да, это тоже хороший вопрос, Как протестировать обновление из Play Store, потому что при попытке протестировать новую версию в эмуляторе просто скажите, что у вас уже есть приложение с этим пакетом, хотите его удалить? и просто удалите приложение и установите его снова, что не является настоящим обновлением из Play Store, верно? :) - person MrVasilev; 17.07.2019
comment
@MrVasilev - Вы можете загрузить последнюю версию в альфа-версии и добавить конкретных пользователей для тестирования. Следовательно, вы сможете протестировать таким образом. Вот ссылка developers.google.com/actions/deploy/release-environments А в продакшене сделать поэтапный выкат сначала на 1% пользователей, потом на 10% и так далее. - person TheAnkush; 17.07.2019

Возможно, это самый простой способ:

private const val IS_DB_RECREATED = "is_database_recreated"

class App : Application(), HasActivityInjector {

    override fun onCreate() {
        super.onCreate()
        val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
        val isDBRecreated = sharedPreferences.getBoolean(IS_DB_RECREATED, false)

        if (!isDBRecreated) {
            deleteDatabase(MyDatabase.DB_NAME)
            sharedPreferences.edit().putBoolean(IS_DB_RECREATED, true).apply()
        }
    }
}

Все данные будут потеряны из базы данных, но когда новая БД будет доступна в первый раз, она будет предварительно заполнена, и я также могу изменить схему.

person MrVasilev    schedule 17.07.2019