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

我用Cursor从数据库中提取logging。 这是完美的工作。 但是,当我使用这个代码时,我在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) 

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

之后,我也有我的数据库中的这个错误。 所以有人告诉我如何在获取logging后获得光标和数据库的安全closures。

Solutions Collecting From Web of "如何安全地closures光标和数据库?"

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

你可以在完成之后closures光标,如下所示:

 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 

要closures数据库(在closures游标之后,或者最好在onDestroy()一个活动中):

 dbhelper.close(); 

在扩展ContentProvider的类中,如果打开数据库连接并将辅助对象设置为onCreate中的实例variables,则可以closures数据库连接。

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

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

每次当你调用这个方法时,数据库将以读模式打开,但是你没有closures数据库,这就是为什么得到这个错误。 从onCreate()方法打开一次,然后closuresdestroy()

同时你可以在获取行之后closures游标,当不再需要游标时closures并设置为null

你也可以参考这个答案 (build议根据Activity的状态closures游标/数据库对象连接的位置)或者这个 (build议如何closuresSQLiteDatabase对象)。 没有必要详细说明什么时候已经写了一次。 尽pipe如此,下面是编码部分的想法。

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

尝试将SQLiteDatabase作为parameter passing给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; }