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
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.
Is creating different cursor for creating sort orders and distribute it in an model clases for alternating sorting style in an listview in android good practice?
titleCursor = context.getContentResolver().query(sourceUri, projection,
null, null, orderByTitle);
timeCursor = context.getContentResolver().query(sourceUri, projection,
null, null, orderByTime);
dateCursor = context.getContentResolver().query(sourceUri, projection,
null, null, orderByDate);
and values of its cursor will be destributed to each models to get the cursor for sorting for alternating sorting in listview? is it a good practice?
You don't have to create a new cursor. You can just change the sort value for the query, if all other things remain constant. That's why it's a parameter, so you alter it's value upon execution of the query.
Instead of creating a different cursor for each sort, you could maintain a string value or some integer value and based on the value inside an if condition simply change the sort parameter like:
if(value.equals("time")) {
cursor = context.getContentResolver().query(sourceUri, projection,
null, null, orderByTime);
}else if(value.equals("title")) {
cursor = context.getContentResolver().query(sourceUri, projection,
null, null, orderByTitle);
}
and so on.
I'm trying to understand how cursors work and I don't understand a portion of this code --
(lifted off of http://www.vogella.com/articles/AndroidSQLite/article.html)
public Comment createComment(String comment) {
ContentValues values = new ContentValues();
values.put(MySQLiteHelper.COLUMN_COMMENT, comment);
long insertId = database.insert(MySQLiteHelper.TABLE_COMMENTS, null,
values);
Cursor cursor = database.query(MySQLiteHelper.TABLE_COMMENTS,
allColumns, MySQLiteHelper.COLUMN_ID + " = " + insertId, null,
null, null, null);
cursor.moveToFirst();
Comment newComment = cursorToComment(cursor);
cursor.close();
return newComment;
}
Can someone please explain what is going on here?
This is what I THINK is going on - He is inserting values into the table under the column named comment. He then does a query setting the cursor to where he added the comment in the table.
Then I am confused on why he does cursor.moveToFirst(). Isn't the cursor pointing to the current comment he just added? I thought he is trying to return the comment he just inserted into the table, so couldn't he just remove the moveToFirst() method?
Cursor cursor = database.query(MySQLiteHelper.TABLE_COMMENTS,
allColumns, MySQLiteHelper.COLUMN_ID + " = " + insertId, null,
null, null, null);
Returns results are cursor object.
cursor.moveToFirst();
Make sure your are pointing to first element in the cursor object (or) cursor is not empty.
Comment newComment = cursorToComment(cursor);
Calling another method to go through the cursor and perform what ever logic coded inside the method, which return Comment object.
cursor.close();
Close the cursor, so that it would be eligible GC and memeory will be free.
return newComment;
Return the comment object to caller.
From the docs at http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
query returns: "A Cursor object, which is positioned before the first entry."
Then, http://developer.android.com/reference/android/database/Cursor.html
says moveToFirst() : "Move the cursor to the first row."
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)
I have a one row database just for saving app data. My goal is to read one column (one value) from it.
This query returns all the columns in a Cursor:
public Cursor readAll() {
return getReadableDatabase().query(tableName, null, null, null, null, null, null);
}
It returns a Cursor with one row in it, just perfect. However, I don't want to read all columns at once, because it's slow as I have blob's in db too.
Instead, I'd like to read just one column at a time, separately. For example, for a column called "TEXT" it would be this:
public Cursor readText() {
String[] projection = new String[]{"TEXT"};
return getReadableDatabase().query(tableName, projection, null, null, null, null, null);
}
However, this won't work, as I get back a Cursor with zero rows.
So, how to read a specific column from SQLiteBatabase in Android?
public Cursor readText() {
return getReadableDatabase().rawQuery("SELECT colName FROM myTable", new String[] {});
}
Syntax seems to be correct. Check please that you use right name of the column. Showing the table generation code and actual query code could help.
You can use this one also
public Cursor readText() {
return getReadableDatabase().rawQuery("SELECT column_name FROM table_name", null);
}