如何安全关闭光标和数据库?

时间:2011-12-16 09:52:36

标签: android database cursor

我使用Cursor从数据库中获取记录。这是完美的工作。但是,当我使用此代码时,我在Logcat中遇到了一些错误

public Cursor fetchAll()
{
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(t1, new String[] {"_id",name, date, prior, time, dateformat}, null, null, null, null, prior); 
    return cursor;
}

我的logcat是 -

12-16 14:49:20.774: E/Database(18611): close() was never explicitly called on database '/data/data/com.android.application/databases/appZ.db' 
12-16 14:49:20.774: E/Database(18611): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1810)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:817)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:851)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:844)
12-16 14:49:20.774: E/Database(18611):  at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:540)
12-16 14:49:20.774: E/Database(18611):  at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:203)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
12-16 14:49:20.774: E/Database(18611):  at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:158)
12-16 14:49:20.774: E/Database(18611):  at com.android.todoapplication.DBHelper.fetchAll(DBHelper.java:91)
12-16 14:49:20.774: E/Database(18611):  at com.android.todoapplication.ApplicationActivity.sc_adapter(ApplicationActivity.java:1210)
12-16 14:49:20.774: E/Database(18611):  at com.android.todoapplication.ApplicationActivity.refresh_data(ApplicationActivity.java:1195)
12-16 14:49:20.774: E/Database(18611):  at com.android.todoapplication.ApplicationActivity.onKeyDown(ApplicationActivity.java:1440)
12-16 14:49:20.774: E/Database(18611):  at android.view.KeyEvent.dispatch(KeyEvent.java:1037)
12-16 14:49:20.774: E/Database(18611):  at android.app.Activity.dispatchKeyEvent(Activity.java:2068)
12-16 14:49:20.774: E/Database(18611):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1643)
12-16 14:49:20.774: E/Database(18611):  at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2471)
12-16 14:49:20.774: E/Database(18611):  at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2441)
12-16 14:49:20.774: E/Database(18611):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1735)
12-16 14:49:20.774: E/Database(18611):  at android.os.Handler.dispatchMessage(Handler.java:99)
12-16 14:49:20.774: E/Database(18611):  at android.os.Looper.loop(Looper.java:123)
12-16 14:49:20.774: E/Database(18611):  at android.app.ActivityThread.main(ActivityThread.java:4627)
12-16 14:49:20.774: E/Database(18611):  at java.lang.reflect.Method.invokeNative(Native Method)
12-16 14:49:20.774: E/Database(18611):  at java.lang.reflect.Method.invoke(Method.java:521)
12-16 14:49:20.774: E/Database(18611):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-16 14:49:20.774: E/Database(18611):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-16 14:49:20.774: E/Database(18611):  at dalvik.system.NativeStart.main(Native Method)

我引用了here的内容。他们告诉使用getReadableDatabase()。我也在使用那种方法。而且,我也使用这种方法,

public Cursor fetchAll()
{
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(t1, new String[] {"_id",name, date, prior, time, dateformat}, null, null, null, null, prior); 
   if (cursor!=null)
    {
        cursor.close();
    }
   if (db!=null)
    {
        db.close();
    }
    return cursor;
}

之后出现错误,如 -

Database wasn't open.

之后,我的数据库中也出现了这个错误。所以任何人都告诉我如何在获取记录后获取光标和数据库的安全关闭。

6 个答案:

答案 0 :(得分:10)

编辑:如果您返回已经关闭的光标,则无法使用它。在调用方法之前打开数据库,然后在调用方法后关闭游标然后关闭数据库。

完成后可以关闭光标:

Cursor cursor = fetchAll();
... // Do your work with the cursor
cursor.close();

或者,如果您正在使用活动中的光标,并且需要重新查询(当活动重新启动,停止...时),您可以使用此:

Cursor cursor = fetchAll();
startManagingCursor(cursor); // Android will take care of the cursor for you
// Do your work with the cursor

关闭数据库(关闭光标后,或者如果最好在onDestroy()内的活动内):

dbhelper.close();

答案 1 :(得分:3)

在扩展ContentProvider的类中,如果要打开数据库连接 并将帮助器设置为onCreate中的实例变量,您可以关闭 关机时的数据库连接。

@Override
public boolean onCreate() {
    mOpenHelper = getDBOpenHelper(); 
    return true;
}
@Override
public void shutdown() {
mOpenHelper.close();
    super.shutdown();
}

答案 2 :(得分:2)

更好的做法是在onResume()中打开它并在onPause()中关闭它。

答案 3 :(得分:1)

您还可以参考此answer(建议您应根据活动状态关闭游标/数据库对象连接的位置)或this one(建议如何关闭SQLiteDatabase对象)。什么时候已经写好了,不需要详细说明。尽管如此,下面是编码部分的想法。

    if (dbCursor != null && dbCursor.moveToFirst()) {
            try {
                              //do stuff
            }  catch (exceptions) {
                              //catch possible exceptions
            } finally {

                if (dbCursor != null && !dbCursor.isClosed()) {
                    dbCursor.close();
                }
            }

答案 4 :(得分:1)

每次调用此方法时,数据库都将以读取模式打开,但您没有关闭数据库,这就是为什么会出现此错误。像onCreate()方法一样打开一次,然后在destroy()

中关闭

虽然你可以在获取行后关闭光标,当不再需要光标然后关闭并设置为null

答案 5 :(得分:0)

尝试将SQLiteDatabase作为参数传递给fetchAll方法:

MyDatabase db = new MyDatabase(this);

....

Cursor myCursor = db.fetchAll(db.getReadableDatabase());

myCursor.close();
db.close();




    public Cursor fetchAll(SQLiteDatabase db, String listName) {
        String sql = "select ID _id, Name from ListName where Name = ? order by ID";
        Cursor c = db.rawQuery(sql, new String[] { listName });
        c.moveToFirst();

        return c;
    }