检测房间迁移完成

Detect Room Migration Completion

有什么方法可以检测到如果用户打开应用程序应该发生迁移,并且还可以检测 Room 数据库的迁移是否完成?

Is there any way that we can detect that migration should happen if the user opens the application?

是的,您可以在 Room 介入之前根据编码版本号检查存储在数据库中的版本号,例如一旦应用程序启动。

例如您可以使用以下方法并调用它:-

public static int getStoredVersion2(String databaseName, Context context) {
    int rv;
    File dbFile = new File(context.getDatabasePath(databaseName).getPath());
    if (dbFile.exists()) {
        SQLiteDatabase db = SQLiteDatabase.openDatabase(dbFile.getPath(), null, 0);
        rv = db.getVersion();
        db.close();
    } else {
        rv = -1;
    }
    return rv;
}

或更少的资源消耗,因为它不会打开数据库,您可以检查 header(偏移量 60 处的 4 个字节,请参见 SQLite Database Format),例如:-

public static int getStoredVersion(String databaseName, Context context) {
    int rv;
    byte[] readBuffer = new byte[4];
    InputStream i;
    try {
        i = new FileInputStream(context.getDatabasePath(databaseName));
        i.skip(60);
        i.read(readBuffer);
        rv = ByteBuffer.wrap(readBuffer).getInt();
        i.close();
    } catch (IOException e) {
        e.printStackTrace(); //?
        rv = -1;
    }
    return rv;
}

detect if the migrations completed for Room Database?

这会有点困难,但如果迁移没有完成,那么它将失败。如果您不执行 AutoMigration,那么您总是可以引入代码作为指示器。

如果你的意思是它做了你想要的那么真的应该在分发迁移之前通过测试来解决这个问题。

你可以做的是在实例化数据库(即获取构建数据库的实例)后立即强制打开数据库,然后做任何需要做的事情。

例如在 Activity 中你可以有这样的东西:-

public class MainActivity extends AppCompatActivity {



    public static final int DBVersion = 2;
    TheDatabase db;
    AllDao dao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d("VERSION","Stored Database Version before Migration is (via file) " + TheDatabase.getStoredVersion("mylist.db",this));
        Log.d("VERSION","Stored Database Version before Migration is (via SQLiteDatabase)" + TheDatabase.getStoredVersion2("mylist.db",this));
        db = TheDatabase.getInstance(this);
        Log.d("VERSION","Stored Database Version after Migration is " + db.getOpenHelper().getWritableDatabase().getVersion());
        dao = db.getAllDao();
        for (Bookmark b: dao.getAll()) {
            Log.d("BOOKMARKINFO","ID = " + b.getId() + " PostTitle = " + b.getPostTitle() + " PostURL =" + b.getPostUrl());
        }
    }
}

以上,当 运行 在新安装时,结果是:-

2021-07-01 06:55:58.229 W/System.err: java.io.FileNotFoundException: /data/user/0/a.a.so67958704javaroomconvertexistingdb/databases/mylist.db (No such file or directory)
2021-07-01 06:55:58.229 W/System.err:     at java.io.FileInputStream.open0(Native Method)
2021-07-01 06:55:58.229 W/System.err:     at java.io.FileInputStream.open(FileInputStream.java:231)
2021-07-01 06:55:58.229 W/System.err:     at java.io.FileInputStream.<init>(FileInputStream.java:165)
2021-07-01 06:55:58.229 W/System.err:     at a.a.so67958704javaroomconvertexistingdb.TheDatabase.getStoredVersion(TheDatabase.java:58)
2021-07-01 06:55:58.230 W/System.err:     at a.a.so67958704javaroomconvertexistingdb.MainActivity.onCreate(MainActivity.java:26)
2021-07-01 06:55:58.230 W/System.err:     at android.app.Activity.performCreate(Activity.java:7136)
2021-07-01 06:55:58.230 W/System.err:     at android.app.Activity.performCreate(Activity.java:7127)
2021-07-01 06:55:58.230 W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
2021-07-01 06:55:58.230 W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
2021-07-01 06:55:58.230 W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
2021-07-01 06:55:58.230 W/System.err:     at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
2021-07-01 06:55:58.230 W/System.err:     at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
2021-07-01 06:55:58.231 W/System.err:     at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
2021-07-01 06:55:58.231 W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
2021-07-01 06:55:58.231 W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:106)
2021-07-01 06:55:58.231 W/System.err:     at android.os.Looper.loop(Looper.java:193)
2021-07-01 06:55:58.231 W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6669)
2021-07-01 06:55:58.231 W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2021-07-01 06:55:58.231 W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
2021-07-01 06:55:58.231 W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2021-07-01 06:55:58.231 D/VERSION: Stored Database Version before Migration is (via file) -1
2021-07-01 06:55:58.232 D/VERSION: Stored Database Version before Migration is (via SQLiteDatabase)-1
2021-07-01 06:55:58.277 D/VERSION: Stored Database Version after Migration is 2
  • 注意找不到文件是因为数据库不存在。异常被捕获并输出到日志(因此 e.printStackTrace(); //? 行中的 ?)
  • 可以看出,迁移前版本为 -1,迁移后为 2。

再次 运行 时(没有数据库更改的新 APK)然后:-

2021-07-01 07:08:20.947 D/VERSION: Stored Database Version before Migration is (via file) 2
2021-07-01 07:08:20.956 D/VERSION: Stored Database Version before Migration is (via SQLiteDatabase)2
2021-07-01 07:08:20.977 D/VERSION: Stored Database Version after Migration is 2
  • 注意文件检查方法 (getStoredVersion) 确实有 disadvantage/flaw 如果更新的版本号更改没有被检查点(如果使用 Write-Ahead 日志记录)那么它可能是incorrect/outdated,getStoredVersion2就没有这个缺点。