最近,我在我的应用程序中使用的SQLite数据库遇到了一些奇怪的行为。它主要是一个IllegalStateException,说:IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:
下面是抛出错误的方法的简化版本。下面是日志。
我对SQLiteDatabases并不熟悉,所以我不确定它是否适合我。此外,我在网上找到的解决方案似乎都不适用于我的案例。
所以基本上,导致这种情况的原因以及如何解决?
5月24日
我一直在进行一些测试,结果db.isOpen()
在false
块if else
下面ContentValues values = new ContentValues();
返回db.isReadOnly()
。在代码中的任何其他位置调用它时,它返回true。
奇怪的是,private void updateAppUsages(@Nullable ArrayList<String> name, @Nullable ArrayList<Action> action, @Nullable ArrayList<Integer> changeAmount) {
SQLiteDatabase db;
db = getWritableDatabase();
String query = "SELECT * FROM " + TABLE_AppTable2 + " WHERE 1";
if (name.size() != action.size() || name.size() != changeAmount.size()) {
Log.e(TAG, "updateAppUsages: Given arrays are of different length. This will not work");
} else {
ArrayList<Integer> returnAmountArray = new ArrayList<>();
Cursor c = db.rawQuery(query, null);
db.beginTransaction();
for (int i = 0; i < name.size(); i++) {
c.moveToFirst();
while(!c.isAfterLast()){
if(c.getString(c.getColumnIndex("name")) != null){
if (c.getString(c.getColumnIndex("name")).equals(name.get(i))) {
returnAmountArray.add(c.getInt(c.getColumnIndex("usages")));
break;
}
}
c.moveToNext();
}
returnAmountArray.add(0);
if (action.get(i) == Action.INCREASE) {
returnAmountArray.set(i, returnAmountArray.get(i) + changeAmount.get(i));
} else if (action.get(i) == Action.DECREASE) {
returnAmountArray.set(i, returnAmountArray.get(i) - changeAmount.get(i));
if (returnAmountArray.get(i) < 0) {
Log.e(TAG, "DBHandler; appUsages: 'returnAmount' below zero. Can't be less then nothing (" + returnAmountArray.get(i) + ")");
return;
}
}
ContentValues values = new ContentValues();
if (returnArray(AppManagerUsages.AppManagerUsages, AMUStringArg.Name).contains(name.get(i))) {
int id = returnID(Base.AppManagerUsages, name.get(i));
values.put(AT2_COLUMN_NAME, name.get(i));
values.put(AT2_COLUMN_USAGES, returnAmountArray.get(i));
db.update(TABLE_AppTable2, values, "_id=" + id, null);
} else {
values.put(AT2_COLUMN_NAME, name.get(i));
values.put(AT2_COLUMN_USAGES, returnAmountArray.get(i));
db.insert(TABLE_AppTable2, null, values);
}
}
db.setTransactionSuccessful();
db.endTransaction();
c.close();
}
if (db.isOpen()) {
db.close();
}
}
在任何地方都返回false(如果没有打开数据库,则会出现错误/ null)。
05-23 17:03:54.733 3671-3671/com.example.tim.timapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.tim.timapp, PID: 3671
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/user/0/com.example.tim.timapp/databases/TimDatabase.db
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1439)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
at com.example.tim.timapp.CustomStuff.DBHandler.updateAppUsages(DBHandler.java:566)
at com.example.tim.timapp.CustomStuff.DBHandler.updateAppUsages(DBHandler.java:513)
at com.example.fragments.MainFragments.DialogFragments.AppManagerInputDialog$1.onClick(AppManagerInputDialog.java:83)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
DecimalFormat
答案 0 :(得分:0)
显然,这不是正确的做法。
从here复制:
我不相信你每次都应该像这样获得一个新的SQLiteDatabase实例。您希望在SQLiteOpenHelper中保留对SQLiteDatabase对象的引用。您的SQLiteOpenHelper应该构造成类似于以下内容的东西:
public class DataBase extends SQLiteOpenHelper {
...
private SQLiteDatabase mDatabase;
@Override
public void onCreate(SQLiteDatabase db) {
...
mDatabase = db;
...
}
....
}
结合this评论,我在自己的SQLiteOpenHelper
课程中为自己创建了这个:
private static SQLiteDatabase db;
public static synchronized DBHandler getInstance(Context context) {
if (sInstance == null) {
sInstance = new DBHandler(context.getApplicationContext());
db = sInstance.getWritableDatabase();
}
return sInstance;
}
到目前为止,这一直在运行干净并且没有给我任何错误,所以这里希望它保持这种状态。