My code is like below:
Cursor getResults() {
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, null, null,
null, null, null);
db.close();
return c;
}
My question is, after db.close() is executed, is the cursor c still alive and navigable?
Thanks.
No. You do not want to use a cursor while the database is closed. When you call close(), it makes the object (and it's corresponding cursor) invalid.
Related
SQLiteDatabase db = mDbHelper.getReadableDatabase();
String[] projection = {
HistoryEntry._ID,
HistoryEntry.COLUMN_HISTORY_INPUT,
HistoryEntry.COLUMN_HISTORY_RESULT
};
Cursor cursor = db.query(HistoryEntry.TABLE_NAME,
projection,
null,
null,
null,
null,
null);
ListView historyListView = (ListView) findViewById(R.id.list);
mCursorAdaptor = new HistoryCursorAdaptor(this, cursor);
historyListView.setAdapter(mCursorAdaptor);
//the code is using to read data from database but error in query. says ," free up cursor after use."
you need to call cursor.close() to release the cursor and its resources but as per your code, once we close the cursor then your adapter won't be able to access it, so the idle place will be to close the cursor inside onDestroy method of activity life cycle and for that, you can declare cursor as global variable (outside current method)
Assuming HistoryCursorAdaptor is a CursorAdapter, it takes ownership of the passed in Cursor and you should not be closing it yourself.
If you want to explicitly close the cursor owned by a cursor adapter, you can call changeCursor(null) on the adapter.
I understand that a after a database is closed, the cursor becomes "invalid", does that also close the cursor at the same time? Does that avoid having to do what is shown below?
example 1
public void String getResultsAndReturnString() {
String result = "";
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = qb.query(db, projection, null, null,
null, null, null);
cursor.close(); <-- explicit cursor close example one
db.close();
return result;
}
example 2
public void Cursor getResultsAndReturnCursor(){
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = qb.query(db, projection, null, null,
null, null, null);
return cursor;
}
public void closeOut(Cursor cursor, SQLiteDatabase dataBase){
cursor.close(); <-- explicit cursor close example two
dataBase.close();
}
The cursor isn't closed in the strict sense by closing the database (it's still there and you can perform operations on it), but as you know, closing the database makes the cursor useless. You should close cursors explicitly after you're done using them for a number of reasons:
1) As you noted, after closing the database, any remaining cursors become "invalid," and cannot be relied upon for accurate data;
2) You will see warnings in LogCat;
3) You risk memory leaks if you maintain a reference to a cursor; and
4) It's simply good programming practice to close out resources that you no longer need.
I can't find what causing this error in my database, I posted some question before related to this issue but since the code is quite long i remove some of them that has the same
declaration because stackoverflow won't allow me to post more than 3000 characters. i tried using this method to close the cursor, but somehow it doesn't fix the problem.
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);
} finally {
if(c != null){
c.close();
}
}
return c;
}
Anyway [here's] the whole class I hope someone can help me.
Closing the cursor is the reason why I'm getting this error so instead of this:
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);
} finally {
if(c != null){
c.close();
}
}
return c;
}
I just used this line of code:
public Cursor getMove(){
String[] columns = new String[]{KEY_ID1, KEY_MOVENAME};
Cursor c = null;
c = ourDatabase.query(DATABASE_TABLE1, columns, null, null, null, null, null);
return c;
}
The reason may be that you are using multiple instances of your DB connections and not closing all cursors that you hand out. The answer that you accepted (your own) could be dangerous. Are you releasing the cursors that you hand out from this method ? You will end up taking precious resources on the phone that will never be released if you don't.
You can solve this by maintaining one database instance (by using a singleton to handle the DB connections) and closing all cursors eventually. Either marshal them into POJOs and close the cursors immediately or send back a cursor and manage it with a call to a method like activity.managedQuery(). You might also want to look at android's SQL lite locking mechanism.
In attempting to execute a query on my database, I get this exception. However, the documentation states that the method SQLiteDatabase.query(...) returns, "A Cursor object, which is positioned before the first entry," which I interpret to mean that the Cursor is at the start of the rows returned. If I add the Cursor.moveToFirst() before accessing data in the Cursor, I get no exception. What is going on? Do I need to always call "moveToFirst" before trying to get data? The documentation says this method, "moves the cursor to the first row."
Cursor c = db.query(TABLENAME, null, null, null, null, null, null);
Log.d("TAG",""+c.getInt(c.getColumnIndex("_id")));
After query you need to call next() or moveToFirst(). Cursors are lazy loaded, after calling these methods cursor is loaded into memory. You can decide when to do it.
to iterate trough all rows:
Cursor c = db.query(TABLENAME, null, null, null, null, null, null);
while(c.moveToNext()) {
int id = c.getInt(c.getColumnIndex("_ID"));
}
or you can use other cursor functions, for example moveToPosition() to access row specified by id
more info: http://developer.android.com/reference/android/database/Cursor.html
So I'm trying to get the values from a SQLite database into a cursor, then pick a random value. I can read the cursor with getString() as I normally would in the method, but after it returns the cursor it doesn't work correctly. I don't know why..
Here's my method for getting the cursor from the database. It seems to work correctly.
public Cursor getRandomText(String Rating)
{
Cursor cursor = myDatabase.query("Elec0RandTexts", new String[] {"Message"}, "Rating=?",
new String[]{Rating}, null, null, null);
cursor.moveToFirst();
cursor.close();
return cursor;
}
Here's my code for reading the cursor after it's returned.
Cursor result = dbh.getRandomText(Rating);
result.moveToFirst();
int RandText = rand.nextInt(result.getCount());
result.moveToPosition(RandText);
Toast.makeText(getApplicationContext(), "" + result.getString(RandText), Toast.LENGTH_LONG).show();
result.close();
I'm probably making a stupid mistake and not realizing it, but I can't figure this out.
Thanks,
~Elec0
cursor.close(); // in getRandomText()
after that you cannot obtain any data from the cursor - it is closed. Remove this line.
You close() your Cursor before you return it. From where it is returned to, you are then attempting to call moveToFirst(). This cannot be done if the Cursor is closed.
In your getRandomText(String) method, you should return the meaningful data from your Cursor, rather than the Cursor object itself. That way, the method that created the Cursor can continue to close the Cursor as it should. (It should just happen at the end of the method)