android - 使用 Room 的 createFromAsset() 在数据库文件之间切换会返回空数据库
问题描述
我有一个spinner
用来在SQLite
数据库文件之间切换的。在spinner
选择侦听器上,我将相关的数据库文件名传递给 Room 的 Database 类。
在通过调用 Room's 在数据库之间切换之前createFromAsset()
,我删除了 Room 的数据库文件以避免之前数据库中的数据缓存。
我的问题是,每当我切换到另一个spinner
值时,数据库什么都不返回。从我手机上的应用程序数据中读取数据库文件后,数据库文件就在那里,但表中没有条目。
这是微调器回调:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (mActivateSpinner) {
String newDatabaseName;
switch (position) {
case 0:
newDatabaseName = "database1.db";
break;
case 1:
newDatabaseName = "database2.db";
break;
default:
newDatabaseName = "database1.db";
}
mViewModel.deleteDatabase(newDatabaseName, () -> runOnUiThread(() -> {
//
// Reading database here returns empty data
//
}));
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
ViewModel 相关方法
public class MyViewModel extends AndroidViewModel {
....
MyRepository mRepository;
public void deleteDatabase(String newDatabaseName, OnCompletionListener listener) {
MyRepository.resetInstance();
MyDataBase.resetInstance();
// delete current Room database file
deleteDatabaseFile(getApplication().getApplicationContext(), "MyDataBaseFile.db", () -> initRepository(newDatabaseName, listener));
}
public void initRepository(String newDatabaseName, OnCompletionListener listener) {
mRepository = MyRepository.getInstance(getApplication(), newDatabaseName, listener);
}
public static void deleteDatabaseFile(Context context, String fileName, OnCompletionListener deleteListener) {
new Thread(() -> {
File parent = new File(context.getApplicationInfo().dataDir + "/databases");
File db = new File(parent, fileName);
if (db.delete()) {
deleteListener.onComplete();
Log.d("TAG", "Database deleted");
} else
Log.d("TAG", "Failed to delete database");
}).start();
}
}
存储库相关方法
public class MyRepository {
...
private MyDataBaseDao mDao;
private static MyRepository INSTANCE;
public static MyRepository getInstance(Application application, String databaseName, OnCompletionListener listener) {
if (INSTANCE == null) {
INSTANCE = new MyRepository(application, databaseName, listener);
}
return INSTANCE;
}
private MyRepository(Application application, String databaseName, OnCompletionListener listener) {
mDao = MyDataBase.getInstance(application.getApplicationContext(), databaseName, listener).getDao();
}
}
房间数据库
@Database(entities = {MyTable.class}, version = 1, exportSchema = false)
public abstract class MyDataBase extends RoomDatabase {
public static final String DATABASE_NAME = "MyDataBaseFile.db";
private static volatile MyDataBase INSTANCE;
private static final Object LOCK = new Object();
public abstract MyDataBaseDao getDao();
public static void resetInstance() {
INSTANCE = null;
}
static public MyDataBase getInstance(final Context context, String databaseName, OnCompletionListener listener) {
if (INSTANCE == null) {
synchronized (LOCK) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
MyDataBase.class, DATABASE_NAME)
.createFromAsset("database/" + databaseName)
.build();
if (listener != null)
listener.onComplete();
}
}
}
return INSTANCE;
}
}
被listener.onComplete()
调用,并且数据库文件具有预期的大小,但表没有数据。
解决方案
Room 为每个数据库创建 3 个文件,在我的例子中我命名为 database MyDataBaseFile.db
,然后 Room 创建 3 个文件并命名它们:
- MyDataBaseFile.db
- MyDataBaseFile.db-wal
- MyDataBaseFile.db-shm
当我切换微调器值时,我只是删除MyDataBaseFile.db
并留下了其他两个文件,而删除其他两个文件确实在表中显示了新数据
更新了删除方法
public static void deleteDatabase(Context context, String databaseName, OnCompletionListener deleteListener) {
new Thread(() -> {
File parent = new File(context.getApplicationInfo().dataDir + "/databases");
if (deleteFile(parent, databaseName + "-wal")
&& deleteFile(parent, databaseName + "-shm")
&& deleteFile(parent, databaseName)) {
deleteListener.onComplete();
Log.d(TAG, "Database deleted");
} else
Log.d(TAG, "Failed to delete database");
}).start();
}
/*
* Returns:
* **** true: if the file doesn't exist or successfully deleted
* **** false: if the file can't be deleted
* */
private static boolean deleteFile(File parent, String child) {
File file;
if (parent != null)
file = new File(parent, child);
else
file = new File(child);
if (file.exists())
return file.delete();
else
return true;
}
推荐阅读
- search - VBA conditional search and marking
- python - 除非通过 CMD 输入,否则无法从 python 控制台导入模块
- android - 由于 sym_keyboard_feedback_delete.png 文件,App Bundle 构建失败
- python - 如何在python中计算特征脸?
- angular - 从 css 文件中获取图标列表以在 Angular 6 组件中使用
- teamcity - TeamCity 和日历版本控制
- rust - Is storing data and a mutable pointer to that data in a struct safe?
- python - 为什么 Python wikipedia 包中的“sections”属性返回一个空列表?
- python - When should a single session instance be used for requests?
- java - call data from array by using identifier