使用 Room 的 createFromAsset() returns 空数据库在数据库文件之间切换
Switching between database files using Room's createFromAsset() returns empty database
我有一个 spinner
用来在 SQLite
数据库文件之间切换。在 spinner
选择侦听器上,我将相关的数据库文件名传递给房间的数据库 class。
在通过调用 Room 的 createFromAsset()
来切换数据库之前,我删除了 Room 的数据库文件以避免之前数据库的数据缓存。
我的问题是每当我切换到另一个 spinner
值时,数据库 returns 什么都没有。从我 phone 上的应用程序数据中读取数据库文件后,数据库文件就在那里,但 table 没有条目。
这是旋转器回调:
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()
被调用,并且数据库文件已达到预期大小,但 table 没有数据。
Room 为每个数据库创建了 3 个文件,在我的例子中,我将数据库命名为 MyDataBaseFile.db
,然后 Room 创建了 3 个文件并将它们命名为:
- MyDataBaseFile.db
- MyDataBaseFile.db-wal
- MyDataBaseFile.db-shm
我只是在删除 MyDataBaseFile.db
并在切换微调器值时留下其他两个文件,删除其他两个文件确实显示了 table[=13= 中的新数据]
用
更新了删除方法
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;
}
我有一个 spinner
用来在 SQLite
数据库文件之间切换。在 spinner
选择侦听器上,我将相关的数据库文件名传递给房间的数据库 class。
在通过调用 Room 的 createFromAsset()
来切换数据库之前,我删除了 Room 的数据库文件以避免之前数据库的数据缓存。
我的问题是每当我切换到另一个 spinner
值时,数据库 returns 什么都没有。从我 phone 上的应用程序数据中读取数据库文件后,数据库文件就在那里,但 table 没有条目。
这是旋转器回调:
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()
被调用,并且数据库文件已达到预期大小,但 table 没有数据。
Room 为每个数据库创建了 3 个文件,在我的例子中,我将数据库命名为 MyDataBaseFile.db
,然后 Room 创建了 3 个文件并将它们命名为:
- MyDataBaseFile.db
- MyDataBaseFile.db-wal
- MyDataBaseFile.db-shm
我只是在删除 MyDataBaseFile.db
并在切换微调器值时留下其他两个文件,删除其他两个文件确实显示了 table[=13= 中的新数据]
用
更新了删除方法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;
}