【问题标题】:Android: FC when querying sqlite opened databaseAndroid:查询sqlite打开数据库时的FC
【发布时间】:2012-04-10 02:25:59
【问题描述】:

Android 系统会自动关闭一个打开的 SQLite 数据库吗?我已经实现了一个用于访问数据的单例类,有时那里的方法需要在工作线程上运行。我有一个在后台运行的查询的同步功能,代码如下:

public ArrayList<ActualCall> getUnsentCalls(boolean forUnsentSignature) {
    ArrayList<ActualCall> calls = new ArrayList<ActualCall>();

    Cursor c;
    open();

    if (forUnsentSignature)
        c = db.rawQuery("SELECT * FROM " + TXN_ACTUAL_CALL_COMPONENT
                + " WHERE sentFlag=1 and sigSentFlag=?", new String[] {"0"});
    else
        c = db.rawQuery("SELECT * FROM " + TXN_ACTUAL_CALL_COMPONENT
                + " WHERE sentFlag=? AND signature != ''", new String[] {"0"});

    if (c.moveToFirst()) {
        do {
            if (!db.isOpen())
                open();
            ActualCall call = new ActualCall();

            call.setAcpComponentId(c.getString(c.getColumnIndex("acpComponentId")));
            call.setAcpDate(c.getString(c.getColumnIndex("acpDate")));
            call.setAcpId(c.getString(c.getColumnIndex("acpId")));
            call.setCallEndTime(c.getString(c.getColumnIndex("callEndTime")));
            call.setCallStartTime(c.getString(c.getColumnIndex("callStartTime")));
            call.setCoordinates(c.getString(c.getColumnIndex("coordinates")));
            call.setDeviceTimestamp(c.getString(c.getColumnIndex("deviceTimestamp")));
            call.setDoctorId(c.getString(c.getColumnIndex("doctorId")));
            call.setSignature(c.getString(c.getColumnIndex("signature")));
            call.setSigSentFlag(c.getString(c.getColumnIndex("sigSentFlag")));
            call.setTimeSpent(c.getString(c.getColumnIndex("timeSpent")));
            call.setSentFlag(c.getString(c.getColumnIndex("sentFlag")));
            call.setCoordinates(c.getString(c.getColumnIndex("coordinates")));

            calls.add(call);

        } while (c.moveToNext());
    }

    c.close();
    db.close();

    return calls;
}

如您所见,我已经在最初的几行中调用了 open(),但我收到了一个错误,表明我的数据库已经关闭。这是堆栈跟踪:

 java.lang.IllegalStateException: database    
 /data/data/com.***.****/databases/****.db (conn# 0) already closed
 at android.database.sqlite.SQLiteDatabase.verifyDbIsOpen(SQLiteDatabase.java:2123)
 at android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:398)
 at android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:390)
 at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:74)
 at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:311)
 at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:292)
 at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:156)
 at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:233)
 at com.***.****.datalayer.ESCAndroidDataLayer.getUnsentCalls(ESCAndroidDataLayer.java:5340)
 at com.***.****.synchall.SynchAll$UnsentSignatureSender.run(SynchAll.java:1750)

再一次,上面的方法是在一个 Thread 类上调用的,如果有帮助的话。我找到了一个关于自动关闭 SQLite 的链接,但我不明白他的解决方案:http://darutk-oboegaki.blogspot.com/2011/03/sqlitedatabase-is-closed-automatically.html

【问题讨论】:

    标签: android sqlite thread-safety


    【解决方案1】:

    尝试在 c.moveToFirst() 之前调用 db.acquireReference()

        db.acquireReference();
    
        if (c.moveToFirst()) {
    

    或者只需将 db.close() 与 "if (db.isOpen())" 括起来就足够了。

        if (db.isOpen())
        {
            db.close();
        }
    

    我不太确定,但这些会改变一些事情。

    【讨论】:

    • 我有一个位置获取器在后台工作,它获取一个位置然后将其保存到数据库中。如果碰巧同时发生,我不确定这是否会影响我的其他数据库访问。
    猜你喜欢
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多