我在Android应用程序中使用一个SQLite数据库,可以使用DBHelper和自定义ContentProvider访问该数据库。 我现在想导入数据库,方法是将当前数据库替换为我以前从应用程序导出的数据库,只需将其复制到另一个位置即可。
但是,替换数据库后,将继续使用旧数据库的内存副本,直到我关闭并重新启动该应用程序为止。
->如何强制重新加载数据库?
当我将.db文件与.db-shm和.db-wal文件一起导出并导入所有3个文件而不只是.db文件时,效果很好。
但是,如果我在笔记本电脑上使用sqlite3打开.db文件,请将其关闭(以使.db文件包含所有必需的信息,并且.db-shm和.db-wal将被自动删除),然后尝试导入只是这个.db文件,其行为如上所述。
DBHelper 类:
public class MyDbHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "mydb.db";
private static final int DATABASE_VERSION = 2;
private static MyDbHelper mInstance = null;
MyDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE table1 ...;");
db.execSQL("CREATE TABLE table2 ...;");
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("CREATE TABLE IF NOT EXISTS table3 ...;");
}
static MyDbHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new MyDbHelper(context.getApplicationContext());
}
return mInstance;
}}
在 ContentProvider onCreate()方法中,我以如下方式实例化DBHelper:
mDbHelper = MyDbHelper.getInstance(getContext());
,然后按照建议的here获取ContentProvider中每个方法内部的可写/可读数据库实例。
我尝试在DBHelper中实现重新打开方法
public static void reopen(Context context) {
mDBHelper = new MyDBHelper(context);
}
如建议的here并在导入后调用它,但仍然只有在关闭并重新启动应用程序后才使用新数据库。
我也尝试过重置方法
public void reset(Context context) {
mDBHelper.close();
mDBHelper = new MyDBHelper(context);
}
如here所述,但这会导致应用崩溃,
2019-08-03 14:58:13.091 21814-21887/? E/SQLiteLog: (522) statement aborts at 3: [SELECT _id, title, cover_path FROM albums ORDER BY CAST(title as SIGNED) ASC, LOWER(title) ASC] disk I/O error
2019-08-03 14:58:13.092 21814-21887/? E/SQLiteQuery: exception: disk I/O error (code 522 SQLITE_IOERR_SHORT_READ); query: SELECT _id, title, cover_path FROM albums ORDER BY CAST(title as SIGNED) ASC, LOWER(title) ASC
2019-08-03 14:58:13.115 21814-21887/? E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #4
Process: com.mycompany.myapp, PID: 21814
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:354)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by: android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 522 SQLITE_IOERR_SHORT_READ)
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:859)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:149)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:137)
at android.content.ContentResolver.query(ContentResolver.java:821)
at android.content.ContentResolver.query(ContentResolver.java:752)
at android.content.CursorLoader.loadInBackground(CursorLoader.java:68)
at android.content.CursorLoader.loadInBackground(CursorLoader.java:45)
at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:319)
at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:73)
at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:61)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)