我使用Room进行了两步数据库迁移。迁移必须分两部分进行(v.2-> 3-> 4),因为必须在版本3和版本4之间使用新添加的表进行复杂的数据库操作。
我有一个SharedPreferences
键值对,用于在用户迁移时保存信息。这是为了确保应用程序在迁移到版本4后不会尝试从2迁移到3。
从2到3的迁移只能在用户将应用程序从旧版本更新到新版本时运行。
这在我们的每个测试设备中都有效,但是Google Play的数据为我们提供了许多IllegalStateException崩溃报告,表明数据库试图降级。如果SharedPreferences检查正常工作,则不应发生这种情况。
以供参考。以下是一些迁移代码:
if(!hasMigrated){
if(NeedMigration.needMigrate(MyApplication.getAppContext())){
..
try{
//instantiate migration 2 to 3
pdb=PreDatabase.getInstance(this);
dRepo = new DayRepo(pdb, this, dayInstance);
//db operations
createDays();
//store into SharedPrefs that we already migrated from 3
NeedMigration.setHasMigrated(MyApplication.getAppContext());
}catch(IllegalStateException e){
Log.e("Database", "Already at version 4");
..
return;
}
..
//instantiate migration from 3 to 4 (mig is in db.build)
mdb = MyDatabase.getInstance(this);
mRepo = Repository.fromContext(this);
..
} else {
/*
If the user already has updated and the database exists in its newest state, skip straight to MyDatabase.java
instantiation and load Day objects from database.
*/
instantiateDatabase();
}
..
hasMigrated=true;
}
hasMigrated布尔值只是一个静态布尔值,因此应用程序在运行时不会尝试再次实例化数据库。如果NeedMigration.needMigrate返回false,则仅实例化当前版本的数据库。 这是NeedMigrate类:
private static final String MIG_PREFS= "migration_preferences";
private static final String MIG_HAS_UPDATED ="has_updated_to_four";
//if yes (true) then yes need migrate
//if false then no! no migrate
public static boolean needMigrate(Context activity){
//compare versioncode with sharedprefs
final SharedPreferences preferences = activity.getSharedPreferences(MIG_PREFS, Activity.MODE_PRIVATE);
final boolean needmig = preferences.getBoolean(MIG_HAS_UPDATED, true);
return needmig;
}
public static void setHasMigrated(Context activity){
final SharedPreferences prefs = activity.getSharedPreferences(MIG_PREFS, Activity.MODE_PRIVATE);
//check if value exists
SharedPreferences.Editor edit = prefs.edit();
//false because if needMigrate is false then we dont need migrate
edit.putBoolean(MIG_HAS_UPDATED, false);
edit.commit();
}
再次让我澄清一下,这在我的测试设备上可以很好地工作,但是我们从Google收到了很多崩溃报告,这表明数据库试图在以前的版本上运行:
java.lang.IllegalStateException: 在androidx.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:101) 在androidx.room.RoomOpenHelper.onDowngrade(RoomOpenHelper.java:113) 在androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper $ OpenHelper.onDowngrade上 (FrameworkSQLiteOpenHelper.java:144)在 android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked (SQLiteOpenHelper.java:257)在 android.database.sqlite.SQLiteOpenHelper.getWritableDatabase (SQLiteOpenHelper.java:2)在 androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper $ OpenHelper.getWritableSupportDatabase (FrameworkSQLiteOpenHelper.java:96)在 androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase (FrameworkSQLiteOpenHelper.java:54)在 androidx.room.RoomDatabase.query(RoomDatabase.java:256)在 androidx.room.util.DBUtil.query(DBUtil.java:54)位于 fi ...... controllers.database_controller.MealGroupDao _ .. PreDatabase_Impl.getMealGroupsInDay (MealGroupDao _ .. PreDatabase_Impl.java:157)在 fi ..... DayRepo.lambda $ populateDayCache $ 0(DayRepo.java:301)在 fi ..... controllers.database_controller.repos .- $$ Lambda $ DayRepo $ gQGLM0kHLZLeLseqjFzeMTTO2fw.run (-.java:8)在java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)在 java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:641)在java.lang.Thread.run (Thread.java:764)
我们刚刚收到一条评论,内容为“无法打开应用”,我怀疑这是原因。
为什么此SharedPreference检查被忽略,或者它只是返回错误的值?这是与上下文相关的问题,还是与NeedMigration类是静态的事实有关? 我尝试过: