How to close cursor in android correctly

I have this database using sqlite and I have a problem closing the cursor saying Application did not close the cursor or database object that was opened here here logcat

 10-18 08:40:56.354: E/Cursor(331): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here 10-18 08:40:56.354: E/Cursor(331): at android.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.java:210) 10-18 08:40:56.354: E/Cursor(331): at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:53) 10-18 08:40:56.354: E/Cursor(331): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1345) 10-18 08:40:56.354: E/Cursor(331): at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1229) 10-18 08:40:56.354: E/Cursor(331): at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1184) 10-18 08:40:56.354: E/Cursor(331): at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1264) 10-18 08:40:56.354: E/Cursor(331): at standard.internet.marketing.mymovingfriend.SQLHandler.checkMove(SQLHandler.java:1094) 10-18 08:40:56.354: E/Cursor(331): at standard.internet.marketing.mymovingfriend.ListMovingNames$3.onKey(ListMovingNames.java:98) 10-18 08:40:56.354: E/Cursor(331): at android.view.View.dispatchKeyEvent(View.java:3735) 10-18 08:40:56.354: E/Cursor(331): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788) 10-18 08:40:56.354: E/Cursor(331): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788) 10-18 08:40:56.354: E/Cursor(331): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788) 10-18 08:40:56.354: E/Cursor(331): at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:788) 10-18 08:40:56.354: E/Cursor(331): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1667) 10-18 08:40:56.354: E/Cursor(331): at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1102) 10-18 08:40:56.354: E/Cursor(331): at android.app.Activity.dispatchKeyEvent(Activity.java:2063) 10-18 08:40:56.354: E/Cursor(331): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1643) 10-18 08:40:56.354: E/Cursor(331): at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2471) 10-18 08:40:56.354: E/Cursor(331): at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2441) 10-18 08:40:56.354: E/Cursor(331): at android.view.ViewRoot.handleMessage(ViewRoot.java:1735) 10-18 08:40:56.354: E/Cursor(331): at android.os.Handler.dispatchMessage(Handler.java:99) 10-18 08:40:56.354: E/Cursor(331): at android.os.Looper.loop(Looper.java:123) 10-18 08:40:56.354: E/Cursor(331): at android.app.ActivityThread.main(ActivityThread.java:4627) 10-18 08:40:56.354: E/Cursor(331): at java.lang.reflect.Method.invokeNative(Native Method) 10-18 08:40:56.354: E/Cursor(331): at java.lang.reflect.Method.invoke(Method.java:521) 10-18 08:40:56.354: E/Cursor(331): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 10-18 08:40:56.354: E/Cursor(331): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 10-18 08:40:56.354: E/Cursor(331): at dalvik.system.NativeStart.main(Native Method) 

this problem bugged me for 3 days.

here is the corresponding code:

 public class SQLHandler { public static final String KEY_MOVENAME = "movename"; public static final String KEY_ID1 = "_id"; public static final String KEY_ID5 = "_id"; public static final String KEY_MOVEDATE = "movedate"; public static final String KEY_TOTALMOVEWEIGHT = "totalmoveweight"; public static final String KEY_TOTALITEM = "totalitem"; private static final String DATABASE_NAME = "mymovingfriend"; private static final int DATABASE_VERSION = 1; public static final String KEY_LISTITEMNAME = "listitemname"; public static final String KEY_LISTITEMWEIGHT = "listitemweight"; public static final String KEY_LISTITEMROOM = "listitemroom"; private static final String DATABASE_TABLE1 = "movingname"; private static final String DATABASE_TABLE5 = "listitem"; public static final String CREATE_TABLE_1 = "CREATE TABLE " + DATABASE_TABLE1 + " (" + KEY_ID1 + " INTEGER PRIMARY KEY AUTOINCREMENT," + KEY_MOVEDATE + " TEXT NOT NULL, " + KEY_TOTALMOVEWEIGHT + " TEXT NOT NULL, " + KEY_TOTALITEM + " INTEGER NOT NULL, " + KEY_MOVENAME + " TEXT NOT NULL);"; public static final String CREATE_TABLE_2 = "CREATE TABLE " + DATABASE_TABLE2 + " (" + KEY_ID2 + " INTEGER PRIMARY KEY AUTOINCREMENT," + KEY_ROOMMOVEHOLDER + " TEXT NOT NULL, " + KEY_ROOMWEIGHT + " TEXT NOT NULL, " + KEY_ROOM + " TEXT NOT NULL);"; public static final String CREATE_TABLE_5 = "CREATE TABLE " + DATABASE_TABLE5 + " (" + KEY_ID5 + " INTEGER PRIMARY KEY AUTOINCREMENT," + KEY_LISTITEMNAME + " TEXT NOT NULL, " + KEY_LISTITEMWEIGHT + " TEXT NOT NULL, " + KEY_LISTITEMROOM + " TEXT NOT NULL);"; private DbHelper ourHelper; private final Context ourContext; private SQLiteDatabase ourDatabase; private static class DbHelper extends SQLiteOpenHelper{ public DbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub db.execSQL(CREATE_TABLE_1); db.execSQL(CREATE_TABLE_2); db.execSQL(CREATE_TABLE_3); db.execSQL(CREATE_TABLE_4); db.execSQL(CREATE_TABLE_5); } @Override public void onUpgrade(SQLiteDatabase db, int oldversion, int newversion) { // TODO Auto-generated method stub db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE1); db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE2); db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE3); db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE4); db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE5); onCreate(db); } } public SQLHandler(Context c){ ourContext = c; } public SQLHandler open() throws SQLException{ ourHelper = new DbHelper(ourContext); ourDatabase = ourHelper.getWritableDatabase(); return this; } public void close(){ ourDatabase.close(); ourHelper.close(); } public long createMove(String smovename){ ContentValues cv = new ContentValues(); cv.put(KEY_MOVENAME, smovename); cv.put(KEY_MOVEDATE, "Not yet set"); cv.put(KEY_TOTALMOVEWEIGHT, "0"); cv.put(KEY_TOTALITEM, 0); return ourDatabase.insert(DATABASE_TABLE1, null, cv); } public void createList(){ String[] sroom = new String[]{"Kitchen", "Bedroom", "Dinning Room"}; String[] sitem = new String[]{"Dishwasher", "Bed", "Table"}; String[] sweight = new String[]{"40", "25", "15"}; for (int i = 0; i < sroom.length; i++) { cv.put(KEY_LISTITEMROOM, sroom[i]); cv.put(KEY_LISTITEMNAME, sitem[i]); cv.put(KEY_LISTITEMWEIGHT, sweight[i]); ourDatabase.insert(DATABASE_TABLE5, null, cv); } } public void setMoveDate(String smovedate, String smovename){ ContentValues cv = new ContentValues(); cv.put(KEY_MOVEDATE, smovedate); ourDatabase.update(DATABASE_TABLE1, cv, KEY_MOVENAME + "='" + smovename + "'", null); } public void setMoveWeight(String smoveweight, String smovename){ ContentValues cv = new ContentValues(); cv.put(KEY_TOTALMOVEWEIGHT, smoveweight); ourDatabase.update(DATABASE_TABLE1, cv, KEY_MOVENAME + "='" + smovename + "'", null); } public void setTotalItem(String smovename, int imoveitem){ ContentValues cv = new ContentValues(); cv.put(KEY_TOTALITEM, imoveitem); ourDatabase.update(DATABASE_TABLE1, cv, KEY_MOVENAME + "='" + smovename + "'", null); } public void renameRoom(String movename, String roomname, String currentroom){ ContentValues cv = new ContentValues(); cv.put(KEY_ROOM, roomname); ourDatabase.update(DATABASE_TABLE2, cv, KEY_ROOMMOVEHOLDER + "='" + movename + "'" + " AND " + KEY_ROOM + "='" + currentroom + "'", null); } public void setRoomWeight(String sroomweight, String smovename, String sroomname){ ContentValues cv = new ContentValues(); cv.put(KEY_ROOMWEIGHT, sroomweight); ourDatabase.update(DATABASE_TABLE2, cv, KEY_ROOMMOVEHOLDER + "='" + smovename + "'" + " AND " + KEY_ROOM + "='" + sroomname + "'", null); } public long addRooms(String sroommoveholder, String sroom){ ContentValues cv = new ContentValues(); cv.put(KEY_ROOMMOVEHOLDER, sroommoveholder); cv.put(KEY_ROOM, sroom); cv.put(KEY_ROOMWEIGHT, "0"); return ourDatabase.insert(DATABASE_TABLE2, null, cv); } public long addNewItems(String sitemmoveholder, String sroomholder, String sitemname, String sitemvalue, String sitemweight){ ContentValues cv = new ContentValues(); cv.put(KEY_ITEMMOVEHOLDER, sitemmoveholder); cv.put(KEY_ROOMHOLDER, sroomholder); cv.put(KEY_ITEMNAME, sitemname); cv.put(KEY_ITEMVALUE, sitemvalue); cv.put(KEY_ITEMWEIGHT, sitemweight); return ourDatabase.insert(DATABASE_TABLE3, null, cv); } public void updateItems(String sitemmoveholder, String sroomholder, String sitemname, String sitemvalue, String sitemweight){ ContentValues cv = new ContentValues(); cv.put(KEY_ITEMVALUE, sitemvalue); cv.put(KEY_ITEMWEIGHT, sitemweight); ourDatabase.update(DATABASE_TABLE3, cv, KEY_ITEMMOVEHOLDER + "='" + sitemmoveholder + "'" + " AND " + KEY_ROOMHOLDER + "='" + sroomholder + "'" + " AND " + KEY_ITEMNAME + "='" + sitemname + "'", null); } public Cursor getMove(){ String[] columns = new String[]{KEY_ID1, KEY_MOVENAME}; Cursor c = null; try { c = ourDatabase.query(DATABASE_TABLE1, columns, null, null, null, null, null); } catch (Exception e) { c.close(); } return c; } public String getTotalWeight(String m) throws SQLException{ String[] columns = new String[]{KEY_ID1, KEY_MOVENAME, KEY_MOVEDATE, KEY_TOTALMOVEWEIGHT}; Cursor c = null; try { c = ourDatabase.query(DATABASE_TABLE1, columns, KEY_MOVENAME + "= '" + m + "'", null, null, null, null); if (c != null) { c.moveToFirst(); String totalWeight = c.getString(3); return totalWeight; } } catch (Exception e) { c.close(); } return null; } public String getTotalWeightLBS(String m) throws SQLException{ String[] columns = new String[]{KEY_ID1, KEY_MOVENAME, KEY_MOVEDATE, KEY_TOTALMOVEWEIGHT}; Cursor c = null; try { c = ourDatabase.query(DATABASE_TABLE1, columns, KEY_MOVENAME + "= '" + m + "'", null, null, null, null); if (c != null) { c.moveToFirst(); int x = Integer.parseInt(c.getString(3)) * 7; String totalWeight = "" + x + " lbs"; return totalWeight; } } catch (Exception e) { c.close(); } return null; } public String getDateMove(String md){ String[] columns = new String[]{KEY_ID1, KEY_MOVENAME, KEY_MOVEDATE}; Cursor c = null;try { c = ourDatabase.query(DATABASE_TABLE1, columns, KEY_MOVENAME + "= '" + md + "'", null, null, null, null); if (c != null) { c.moveToFirst(); String moveDate = c.getString(2); return moveDate; } } catch (Exception e) { c.close(); } return null; } public ArrayList<String> loadRooms(String mn) throws SQLException{ String[] columns = new String[]{KEY_ID2, KEY_ROOMMOVEHOLDER, KEY_ROOM}; ArrayList<String> array = new ArrayList<String>(); Cursor c = null; try { c = ourDatabase.query(DATABASE_TABLE2, columns,KEY_ROOMMOVEHOLDER + "='" + mn + "'", null, null, null, null); int iroom = c.getColumnIndex(KEY_ROOM); for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { array.add(c.getString(iroom)); } } catch (Exception e) { c.close(); } return array; } public void deleteMove(String m) throws SQLException{ ourDatabase.delete(DATABASE_TABLE1, KEY_MOVENAME + "='" + m + "'", null); ourDatabase.delete(DATABASE_TABLE2, KEY_ROOMMOVEHOLDER + "='" + m + "'", null); ourDatabase.delete(DATABASE_TABLE3, KEY_ITEMMOVEHOLDER + "='" + m + "'", null); ourDatabase.delete(DATABASE_TABLE4, KEY_TODOMOVE + "='" + m + "'", null); } public ArrayList<String> getitems(){ String[] columns = new String[]{KEY_ID5, KEY_ITEMNAME}; ArrayList<String> items; items = new ArrayList<String>(); Cursor c = null; try { c = ourDatabase.query(DATABASE_TABLE5, columns, null, null, null, null, null); for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { items.add(c.getString(1)); } } catch (Exception e) { c.close(); } return items; } public ArrayList<String> getitemweight(){ String[] columns = new String[]{KEY_ID5, KEY_ITEMWEIGHT}; ArrayList<String> items = new ArrayList<String>(); Cursor c = null; try { c = ourDatabase.query(DATABASE_TABLE5, columns, null, null, null, null, null); for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { items.add(c.getString(1)); } } catch (Exception e) { c.close(); } return items; } public ArrayList<String> getitemclass(){ String[] columns = new String[]{KEY_ID5, KEY_LISTITEMROOM}; ArrayList<String> items = new ArrayList<String>(); Cursor c = null; try { c = ourDatabase.query(DATABASE_TABLE5, columns, null, null, null, null, null); for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { items.add(c.getString(1)); } } catch (Exception e) { c.close(); } return items; } } 
+7
source share
7 answers

You do not close the cursor in getDateMove , getTotalWeightLBS , loadRooms , ...

Wherever the cursor is no longer needed, close it. Use try-finally in these methods, this ensures that the code runs in the finally block even when exceptions occur.

Change the code in your methods as follows:

 try{ // get data from cursor } catch (Exception e) { c.close(); } 

:

 try { // get data from cursor } catch (Exception e) { // exception handling } finally { if(c != null){ c.close(); } } 
+21
source

The closing cursor in finally ensures that it is closed;

 public void myfunc() { Cursor c = null; try { c = ... // Open cursor here return .... // maybe return something } finally { if(c != null) { c.close(); } } } 
+9
source

If an element implements AutoCloseable (as Cursor.class does), I would recommend doing try-with-resources , as described here . If you use Retrolambda, it has a try-with-resources backport.

So your code is:

 Cursor cursor = db.query("tableName", columns, null, null, null, null, null); try { if (cursor.moveToFirst()) return cursor.getString(3); else return null; } finally { cursor.close(); } 

just turn into:

 try (Cursor cursor = db.query("tableName", columns, null, null, null, null, null)) { if (cursor.moveToFirst()) return cursor.getString(3); else return null; } 
+7
source

close your database in the onStop() or onDestroy() method of your activity!

0
source

You are trying to close the cursor inside the catch block using

 catch (Exception e) { c.close(); } 

But if you have not received any exception, then how will it close

so put it in a finally block

 finally { c.close(); } 
0
source

Try it,

In onStop() or onDestroy()

Check if cursor is null

 @Override public void onStop(){ Cursor cursor; if(cursor!=null){ cursor.close();} } 

If not, close the cursor.

EDIT

Close Database Object

 DatabaseObject db; if(db!=null) { db.close();} 

Hope this helps.

0
source

If you use Kotlin (also available in Java in a slightly different way) and Android 4.1 and higher, you can use this:

  cursor?.use { //..do stuff } 

As an example, you can check here .

If you want to use Java, do something like:

  try (Cursor cursor = ...) { // do something } 
0
source

Source: https://habr.com/ru/post/1440487/


All Articles