Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: How to create my own cursor class?

I'm using Sqlite in Android and to get a value from the database I use something like this:

Cursor cursor = sqliteDatabase.rawQuery("select title,category from table", null);

int columnIndexTitle = cursor.getColumnIndex("title");
iny columnIndexCategory = cursor.getColumnIndex("category");

cursor.moveToFirst();
while (cursor.moveToNext()) {
    String title = cursor.getString(columnIndexTitle);  
    String category = cursor.getString(columnIndexCategory);    
}
cursor.close();

I want to create my own Cursor so that I can do getColumnIndex() and getString() with one method. Something like this:

String title = cursor.getString("title");

I want to create my own class that extends the cursor that I get from sqliteDatabase.rawQuery, but I'm not sure how to accomplish this. Should I extend SQLiteCursor or how should I do this? Is it even a possible and is it a good idea?

like image 905
Martin Avatar asked Apr 12 '11 18:04

Martin


People also ask

Why is Cursor class used in Android?

Introduction to Cursor in Android The basic purpose of a cursor is to point to a single row of the result fetched by the query. We load the row pointed by the cursor object. By using cursor we can save lot of ram and memory. Here, we pass the table name, column name only then we receive the cursor.

What does the startManagingCursor () function do?

startManagingCursor does not retain the Cursor's state across configuration changes. Instead, each time the Activity is destroyed due to a configuration change (a simple orientation change, for example), the Cursor is destroyed and must be requeried.

What is Cursor moveToFirst?

moveToFirst() method moves the cursor to the first row. It allows to perform a test whether the query returned an empty set or not.

What is ContentValues Android SQLite?

ContentValues is a maplike class that matches a value to a String key. It contains multiple overloaded put methods that enforce type safety. Here is a list of the put methods supported by ContentValues: void put(String key, Byte value) void put(String key, Integer value)


2 Answers

I came across this question looking for the best way to create a custom Cursor to use together with a SQLiteDatabase. In my case I needed an extra attribute to the Cursor to carry an additional piece of information, so my use case is not exactly as in the body of the question. Posting my findings in hope it will be helpful.

The tricky part for me was that the SQLiteDatabase query methods returns a Cursor, and I needed to pass on a custom subclass to Cursor.

I found the solution in the Android API: Use the CursorWrapper class. It seems to be designed exactly for this.

The class:

public class MyCustomCursor extends CursorWrapper {

    public MyCustomCursor(Cursor cursor) {
        super(cursor);
    }

    private int myAddedAttribute;

    public int getMyAddedAttribute() {
        return myAddedAttribute;
    }

    public void setMyAddedAttribute(int myAddedAttribute) {
        this.myAddedAttribute = myAddedAttribute;
    }

}

Usage:

public MyCustomCursor getCursor(...) {
    SQLiteDatabase DB = ...;
    Cursor rawCursor = DB.query(...);
    MyCustomCursor myCursor = new MyCustomCursor(rawCursor);
    myCursor.setMyAddedAttribute(...);
    return myCursor;
}
like image 150
AnnTea Avatar answered Sep 21 '22 20:09

AnnTea


Creating your own getString will cause a map lookup for each call instead of only for getColumnIndex.

Here's the code for SQLiteCursor.getColumnIndex and AbstractCursor.getColumnIndex. If you have many rows, reducing calls to this function will prevent unnecessary string processing and map lookups.

like image 39
idbrii Avatar answered Sep 20 '22 20:09

idbrii