【发布时间】:2014-12-27 00:55:20
【问题描述】:
所以我尝试使用单独的线程将数据保存到数据库,但这会导致异常:
java.lang.IllegalStateException:数据库未打开
我认为这不是Loader 的任务,因为我不需要任何结果游标,它只是为了保存我的数据。保存到 db 代码如下所示:
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dbHelper.saveMessages(messages);
}
});
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
如果我从线程中删除此数据库操作,一切正常,但会导致 UI 滞后。如果我尝试从单独的线程读取数据库,也会发生同样的事情。
这是数据库编写代码的一部分:
SQLiteDatabase db = dbAdapter.getWritableDatabase());
try {
if (existingMessage != null)
insertId = db.update(Tables.Messages.TABLE_NAME, values, Tables.Messages.SERVER_ID + "=?", new String[]{String.valueOf(message.serverId)});
else
insertId = db.insertOrThrow(Tables.Messages.TABLE_NAME, null, values);
} catch (Exception e) {
e.printStackTrace();
}
实际上异常发生在 db.update() 或 db.insertOrThrow() 行。它不保证会抛出异常,但它会不时发生。例如,它可以写入 5 个对象,然后在 6 日失败。
我在做什么错或 SQLiteOpenHelper 有什么问题?
完整的异常日志:
10-30 22:34:52.746 10431-10536/com.myapp W/System.err﹕ java.lang.IllegalStateException: database not open
10-30 22:34:52.746 10431-10536/com.myapp W/System.err﹕ at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1224)
10-30 22:34:52.746 10431-10536/com.myapp W/System.err﹕ at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1184)
10-30 22:34:52.746 10431-10536/com.myapp W/System.err﹕ at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1264)
10-30 22:34:52.746 10431-10536/com.myapp W/System.err﹕ at com.myapp.db.DatabaseHelper.saveMessages(DatabaseHelper.java:478)
10-30 22:34:52.746 10431-10536/com.myapp W/System.err﹕ at com.myapp.db.DatabaseHelper.requestMessages(DatabaseHelper.java:1245)
10-30 22:34:52.746 10431-10536/com.myapp W/System.err﹕ at com.myapp.activity.LoginActivity$9.run(LoginActivity.java:425)
10-30 22:34:52.746 10431-10536/com.myapp W/System.err﹕ at java.lang.Thread.run(Thread.java:1096)
更新:
我发现它实际上都是关于从 db 读取的。在我的代码中,我首先从 db 读取以确保没有这样的记录。之后我决定做什么——插入或更新。这个问题发生在可读的数据库上。在打开 db 进行读取之后,下一行应该从 db 读取,它显示为“未打开”。而且没有阅读线程,一切都发生在一个线程中:第一次读取然后写入。然而,随机阅读有时会失败。所以它不像我之前提到的那样写。
【问题讨论】:
-
确切的堆栈跟踪是什么以及它出现在您的代码中的什么位置?也发布
saveMessages()代码。 -
您可能没有非常仔细地处理多线程。看this question。它的一些答案可能会有所帮助。
-
其实我想知道你为什么不使用 AtomicInteger 而不是只为 counter++ 或 -- 锁定一个假对象。无论如何,我正在使用 Dmytro Danylyk 的解决方案。但是,我的问题与多线程无关,因为没有其他线程同时使用 db 来读取或写入。
-
这不是导致异常的代码。代码中没有
query(),但堆栈跟踪中有。 -
@Stan,好点;我改变了它。如果您正在使用该解决方案,则不应使用
getWritableDatabase()。您应该使用openDatabase()和closeDatabase()。此外,您可以在 open 和 close 方法中添加一条日志消息,以确保您关闭的次数不会超过打开的次数。
标签: java android multithreading sqlite