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

时间:2022-05-23 07:15:08

I've fetched the records from Database using Cursor. It's work perfect. But, I've some errors in Logcat while i'm using this code

我使用游标从数据库中获取记录。它的工作完美。但是,我在使用这段代码时,在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;
}

My logcat is -

我的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)

I refered something from here. They told that use getReadableDatabase(). I'm using that method also. And, i've also use this method,

我从这里引用了一些东西。他们告诉我们使用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;
}

after that having error like -

在那之后有误差像-

Database wasn't open.

After, also i've this errors in my Database. So anyone tell me How do I acquire the safety close for Cursor and Database after fetching the records.

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

6 个解决方案

#1


10  

EDIT: If you return a cursor that is already closed, you can't use it. Open the database before calling the method, then close the cursor and then the database after calling the method.

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

You can close the cursor after you're done with it like this:

您可以关闭光标后,您做了如下:

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

Or if you're using the cursor from an activity, and need to requery (when the activity is restarted, stopped...) you can use this:

或者,如果您正在使用活动中的游标,并且需要重新请求(当活动重新启动、停止…),您可以使用以下命令:

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

To close database (after closing the cursor, or if inside an activity in onDestroy() preferably):

关闭数据库(在关闭光标之后,或者在onDestroy()中的活动中关闭):

dbhelper.close();

#2


3  

In your class which extends ContentProvider, if you are opening the database connection and setting the helper as an instance variable in onCreate, you can close the database connection in shutdown.

在扩展ContentProvider的类中,如果打开数据库连接并在onCreate中将helper设置为实例变量,那么可以在shutdown中关闭数据库连接。

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

#3


2  

Better practice would be- open it in onResume() and close it in onPause().

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

#4


1  

every time when you call this method database will open in read mode you but you didn't close the database that's why getting this error. open just once like from onCreate() method and close in destroy()

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

while you can close the cursor after fetching the rows and when there is no more need for cursor then close and set to null

当您可以在获取行后关闭游标,当不再需要游标时,则关闭并设置为null

#5


1  

You can also refer to this answer (suggests where you should close cursors/db objects connections depending on the state of Activity) or this one (suggests how to close SQLiteDatabase object). No need to elaborate when it's already written once. Despite that, below is idea for the coding part.

您还可以参考这个答案(根据活动的状态建议关闭游标/db对象连接的位置)或这个答案(建议如何关闭SQLiteDatabase对象)。当它已经写过一次的时候,不需要详细说明。尽管如此,下面是编码部分的想法。

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

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

#6


0  

Try passing SQLiteDatabase as a parameter to your fetchAll method:

尝试将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;
    }

#1


10  

EDIT: If you return a cursor that is already closed, you can't use it. Open the database before calling the method, then close the cursor and then the database after calling the method.

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

You can close the cursor after you're done with it like this:

您可以关闭光标后,您做了如下:

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

Or if you're using the cursor from an activity, and need to requery (when the activity is restarted, stopped...) you can use this:

或者,如果您正在使用活动中的游标,并且需要重新请求(当活动重新启动、停止…),您可以使用以下命令:

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

To close database (after closing the cursor, or if inside an activity in onDestroy() preferably):

关闭数据库(在关闭光标之后,或者在onDestroy()中的活动中关闭):

dbhelper.close();

#2


3  

In your class which extends ContentProvider, if you are opening the database connection and setting the helper as an instance variable in onCreate, you can close the database connection in shutdown.

在扩展ContentProvider的类中,如果打开数据库连接并在onCreate中将helper设置为实例变量,那么可以在shutdown中关闭数据库连接。

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

#3


2  

Better practice would be- open it in onResume() and close it in onPause().

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

#4


1  

every time when you call this method database will open in read mode you but you didn't close the database that's why getting this error. open just once like from onCreate() method and close in destroy()

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

while you can close the cursor after fetching the rows and when there is no more need for cursor then close and set to null

当您可以在获取行后关闭游标,当不再需要游标时,则关闭并设置为null

#5


1  

You can also refer to this answer (suggests where you should close cursors/db objects connections depending on the state of Activity) or this one (suggests how to close SQLiteDatabase object). No need to elaborate when it's already written once. Despite that, below is idea for the coding part.

您还可以参考这个答案(根据活动的状态建议关闭游标/db对象连接的位置)或这个答案(建议如何关闭SQLiteDatabase对象)。当它已经写过一次的时候,不需要详细说明。尽管如此,下面是编码部分的想法。

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

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

#6


0  

Try passing SQLiteDatabase as a parameter to your fetchAll method:

尝试将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;
    }