Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/179.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java android:在单独的线程中保存到数据库导致异常数据库关闭_Java_Android_Multithreading_Sqlite - Fatal编程技术网

Java android:在单独的线程中保存到数据库导致异常数据库关闭

Java android:在单独的线程中保存到数据库导致异常数据库关闭,java,android,multithreading,sqlite,Java,Android,Multithreading,Sqlite,因此,我试图使用单独的线程将数据保存到数据库中,但这会导致异常: java.lang.IllegalStateException:数据库未打开 我假设这不是加载程序的任务,因为我不需要任何结果游标,它只需要保存我的数据。“保存到数据库”代码如下所示: Thread thread = new Thread(new Runnable() { @Override public void run() { dbHelper.saveMessages(messages);

因此,我试图使用单独的线程将数据保存到数据库中,但这会导致异常:

java.lang.IllegalStateException:数据库未打开

我假设这不是
加载程序的任务,因为我不需要任何结果游标,它只需要保存我的数据。“保存到数据库”代码如下所示:

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        dbHelper.saveMessages(messages);
    }
});
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
如果我从一个线程中删除这个DB操作,一切正常,但它会导致UI延迟。如果我试图从单独的线程读取DB,也会发生同样的情况。
这是DB编写代码的一部分:

    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中读取,以确保没有这样的记录。之后,我决定做什么-插入或更新。这个问题发生在可读数据库中。数据库打开读取后,下一行应该从数据库中读取,此时显示“未打开”。而且没有读线程,一切都发生在一个线程中:先读然后写。然而,随机阅读有时会失败。所以它不像我之前提到的那样写。

我发现您的实现存在多个问题。第一个dbHelper可以被另一个线程使用,并且可能会创建死锁,因此您应该使用锁来保护它proceedToNextActivity()看起来像是在UI上做一些工作,从后台线程执行任何操作都是错误的,会导致崩溃


如果dbHelper不需要任何UI元素,只需将消息副本传递到此线程,并创建dbHelper->Dosomework->CloseHelper->EndThread。希望这能解决您的问题。

创建一个插入或更新方法。如果由于重复的键而导致插入失败,则更新。

因为我使用()我犯了一个错误,认为出于读取目的,我应该使用标准
getReadableDatabase()返回的可读数据库。
方法。相反,我应该始终使用由
openDatabase()
方法(线程安全)返回的可写的堆栈跟踪。

确切的堆栈跟踪是什么,它出现在代码中的什么位置?也发布
saveMessages()
代码。您可能没有非常小心地使用多线程。看看它的一些答案可能会有所帮助。事实上,我想知道为什么你不使用AtomicInteger而不是仅仅为计数器++或--锁定一个伪对象。不管怎样,我使用的是Dmytro Danylyk的解决方案。然而,我的问题不是关于多线程,因为没有其他线程同时使用db读写。这不是导致异常的代码。代码中没有
query()
,但stacktrace中有。@Stan,说得好;我改了。如果使用的是
getWritableDatabase()
,则不应使用该解决方案。您应该使用
openDatabase()
closeDatabase()
。此外,您可以将日志消息添加到“打开”和“关闭”方法中,以确保关闭的次数不会超过打开的次数。
proceedToNextActivity()
对UI没有任何作用,无论如何,这不是问题的一部分。至于
dbHelper
它理论上可以被其他线程使用,但实际上不是-1,这个答案并没有回答这个问题,也没有解决抛出的
IllegalStateException
。如果有的话,这应该留作注释。我无法想象没有insert\u或\u update方法的数据库。您说过这发生在更新时,很可能您没有处理重复的密钥。更新失败,然后执行插入。