当我进入设备文件资源管理器并搜索应该创建数据库文件的路径时,它不存在。
可能的原因(无法确定)是您没有访问数据库(例如,使用其中一个 dao 添加某些内容或尝试检索某些内容)。这是因为只有在尝试打开数据库时才会实际创建数据库。
您可以使用(例如)强制打开而不是使用 Dao(例如 NoteDao.getAll()):-
private static AppDatabase buildDatabaseInstance(Context context) {
AppDatabase db = Room.databaseBuilder(context,
AppDatabase.class,
"exampleDB")
.allowMainThreadQueries().build();
db.getOpenHelper().getWritableDatabase(); //<<<<< Forces an Open
return db;
}
也许考虑对您的代码进行以下修改,以便(最终)打开 2 个数据库(相同的名称以及它们是否被强制打开)。
添加了回调,以便在调用 onCreate 和 onOpen 时将表示发生的事件的输出写入日志。
所以修改后的@Database类AppDatabase是:-
@Database(entities = {Note.class},version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract NoteDao NoteDao();
private static AppDatabase noteDB;
public static final String TAG = "OPENINFO"; /* added */
/* not used for demo */
public static AppDatabase getInstance(Context context, String dbName, boolean forceOpen) {
if (null == noteDB) {
noteDB = buildDatabaseInstance(context,dbName,forceOpen);
}
return noteDB;
}
/* made public and added ability to pass dbname and also boolean to force open or not */
public static AppDatabase buildDatabaseInstance(Context context, String dbName, boolean forceOpen) {
AppDatabase db = Room.databaseBuilder(context,
AppDatabase.class,
dbName)
/* ADDED callbacks to allow open and create to be logged */
.addCallback(new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
Log.d(TAG,"OnCreate callback invoked for " + dbName);
}
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
Log.d(TAG,"onOpen callback invoked for " + dbName);
}
@Override
public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
super.onDestructiveMigration(db);
}
})
.allowMainThreadQueries().build();
if (forceOpen) {
db.getOpenHelper().getWritableDatabase();
}
return db;
}
/* Placed in here to keep everything together */
/* Slightly modified and made public */
public static String doesDatabaseExist(Context context, String dbName) {
File dbFile = context.getDatabasePath(dbName);
String path = dbFile.getAbsolutePath();
return String.valueOf(dbFile.exists());
}
/* Will close DB if it is open */
public void cleanUp(){
if (noteDB != null && noteDB.isOpen()) {
noteDB.close();
}
noteDB = null;
}
}
在活动中使用以下代码:-
public class MainActivity extends AppCompatActivity {
AppDatabase db1, db2;
NoteDao dao1,dao2;
private static final String db1Name = "example1";
private static final String db2name = "example2";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* First run then neither file should exist at this stage, subsequent runs they will exist */
Log.d(AppDatabase.TAG,"File exists for " + db1Name + " " + AppDatabase.doesDatabaseExist(this,db1Name));
Log.d(AppDatabase.TAG,"File exists for " + db2name + " " + AppDatabase.doesDatabaseExist(this,db2name));
Log.d(AppDatabase.TAG,"Getting instance for " + db1Name + " not force opened");
db1 = AppDatabase.buildDatabaseInstance(this,db1Name,false); /* not force open */
Log.d(AppDatabase.TAG,"Getting instance for " + db2name + " force opened");
db2 = AppDatabase.buildDatabaseInstance(this,db2name,true);
Log.d(AppDatabase.TAG,"File exists for " + db1Name + " " + AppDatabase.doesDatabaseExist(this,db1Name));
Log.d(AppDatabase.TAG,"File exists for " + db2name + " " + AppDatabase.doesDatabaseExist(this,db2name));
dao1 = db1.NoteDao();
dao2 = db2.NoteDao();
Log.d(AppDatabase.TAG,"Dao retrieved for " + db1Name + " accessing db via Dao");
dao1.getAll(); /* will open DB */
Log.d(AppDatabase.TAG,"Dao retrieved for " + db2name + " accessing via Dao");
dao2.getAll(); /* would open DB BUT DB already opened */
Log.d(AppDatabase.TAG,"File exists for " + db1Name + " " + AppDatabase.doesDatabaseExist(this,db1Name));
Log.d(AppDatabase.TAG,"File exists for " + db2name + " " + AppDatabase.doesDatabaseExist(this,db2name));
}
}
第一次运行时,日志包括:-
2021-09-21 10:47:54.405 D/OPENINFO: File exists for example1 false
2021-09-21 10:47:54.405 D/OPENINFO: File exists for example2 false
2021-09-21 10:47:54.406 D/OPENINFO: Getting instance for example1 not force opened
2021-09-21 10:47:54.415 D/OPENINFO: Getting instance for example2 force opened
2021-09-21 10:47:54.443 D/OPENINFO: OnCreate callback invoked for example2
2021-09-21 10:47:54.450 D/OPENINFO: onOpen callback invoked for example2
2021-09-21 10:47:54.450 D/OPENINFO: File exists for example1 false
2021-09-21 10:47:54.450 D/OPENINFO: File exists for example2 true
2021-09-21 10:47:54.454 D/OPENINFO: Dao retrieved for example1 accessing db via Dao
2021-09-21 10:47:54.478 D/OPENINFO: OnCreate callback invoked for example1
2021-09-21 10:47:54.483 D/OPENINFO: onOpen callback invoked for example1
2021-09-21 10:47:54.487 D/OPENINFO: Dao retrieved for example2 accessing via Dao
2021-09-21 10:47:54.490 D/OPENINFO: File exists for example1 true
2021-09-21 10:47:54.490 D/OPENINFO: File exists for example2 true
可以看出,example2(强制打开)的文件在检索实例后存在,而 example1 在尝试通过 getAll() 检索数据之前不存在。
确认相同的回调的输出。
从 DeviceExplorer 的角度来看,如果代码只是(仅限首次运行):-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* First run then neither file should exist at this stage, subsequent runs they will exist */
Log.d(AppDatabase.TAG, "File exists for " + db1Name + " " + AppDatabase.doesDatabaseExist(this, db1Name));
Log.d(AppDatabase.TAG, "File exists for " + db2name + " " + AppDatabase.doesDatabaseExist(this, db2name));
Log.d(AppDatabase.TAG, "Getting instance for " + db1Name + " not force opened");
db1 = AppDatabase.buildDatabaseInstance(this, db1Name, false); /* not force open */
Log.d(AppDatabase.TAG, "Getting instance for " + db2name + " force opened");
db2 = AppDatabase.buildDatabaseInstance(this, db2name, true);
Log.d(AppDatabase.TAG, "File exists for " + db1Name + " " + AppDatabase.doesDatabaseExist(this, db1Name));
Log.d(AppDatabase.TAG, "File exists for " + db2name + " " + AppDatabase.doesDatabaseExist(this, db2name));
}
然后设备资源管理器显示:-
即示例 2 已创建,但示例 1 未创建
如果运行活动的完整代码(仅限第一次运行),则:-