Android:如何创建自己的游标类?

时间:2011-04-12 18:24:51

标签: android database sqlite cursor extend

我在Android中使用Sqlite并从数据库中获取值,我使用类似这样的内容:

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();

我想创建自己的Cursor,以便我可以使用一种方法执行getColumnIndex()getString()。像这样:

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

我想创建自己的类来扩展我从sqliteDatabase.rawQuery得到的光标,但我不知道如何实现这一点。我应该扩展SQLiteCursor还是应该如何做?它甚至可能是一个好主意吗?

5 个答案:

答案 0 :(得分:4)

我遇到了这个问题,寻找创建自定义Cursor以与SQLiteDatabase一起使用的最佳方法。在我的情况下,我需要一个额外的属性Cursor来携带一个额外的信息,所以我的用例并不完全像问题的主体。发表我的发现希望它会有所帮助。

对我来说棘手的部分是SQLiteDatabase查询方法返回一个Cursor,我需要将一个自定义子类传递给Cursor。

我在Android API中找到了解决方案:使用CursorWrapper类。它似乎是为此而设计的。

班级:

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;
    }

}

用法:

public MyCustomCursor getCursor(...) {
    SQLiteDatabase DB = ...;
    Cursor rawCursor = DB.query(...);
    MyCustomCursor myCursor = new MyCustomCursor(rawCursor);
    myCursor.setMyAddedAttribute(...);
    return myCursor;
}

答案 1 :(得分:3)

创建自己的getString将导致每个调用的地图查找,而不仅仅是getColumnIndex。

这是the code for SQLiteCursor.getColumnIndexAbstractCursor.getColumnIndex。如果你有很多行,减少对这个函数的调用将防止不必要的字符串处理和映射查找。

答案 2 :(得分:2)

我不会延长它,我会帮忙:

class MartinCursor {
    private Cursor cursor;

    MartinCursor(Cursor cursor) {
        this.cursor = cursor;
    }

    String getString(String column) {
        ....
    }
}

class MartinCursorHelper {
    static String getString(Cursor cursor, String column) {
        ....
    }
}

就个人而言,我会做后者,除非你讨厌一直提供这个额外的论点。

编辑:我忘了提到pydave的重点:如果你在循环中调用它,那么你就会对自己的性能产生明显的影响。首选方法是查找索引一次,缓存它,然后使用它。

答案 3 :(得分:0)

你应该使用Android SDK中已经存在的DatabaseUtils .stringForQuery()静态方法来轻松检索一个值,这个例子适用于String bot,还有{{1}的方法}}

Long

在db上运行查询并返回第一行第一列中的值的实用程序方法。

这样的东西
stringForQuery(SQLiteDatabase db, String query, String[] selectionArgs)

答案 4 :(得分:0)

遇到这个寻找不同的解决方案,但只想添加这个,因为我相信答案是不能令人满意的。

您可以轻松创建自己的游标类。为了允许需要Cursor的函数接受它,它必须扩展AbstractCursor。要克服系统不使用您的类的问题,您只需将您的类作为包装器。

这里有一个非常好的例子。 https://android.googlesource.com/platform/packages/apps/Contacts/+/8df53636fe956713cc3c13d9051aeb1982074286/src/com/android/contacts/calllog/ExtendedCursor.java

public class ExtendedCursor extends AbstractCursor {
/** The cursor to wrap. */
private final Cursor mCursor;
/** The name of the additional column. */
private final String mColumnName;
/** The value to be assigned to the additional column. */
private final Object mValue;
/**
 * Creates a new cursor which extends the given cursor by adding a column with a constant value.
 *
 * @param cursor the cursor to extend
 * @param columnName the name of the additional column
 * @param value the value to be assigned to the additional column
 */
public ExtendedCursor(Cursor cursor, String columnName, Object value) {
    mCursor = cursor;
    mColumnName = columnName;
    mValue = value;
}
@Override
public int getCount() {
    return mCursor.getCount();
}
@Override
public String[] getColumnNames() {
    String[] columnNames = mCursor.getColumnNames();
    int length = columnNames.length;
    String[] extendedColumnNames = new String[length + 1];
    System.arraycopy(columnNames, 0, extendedColumnNames, 0, length);
    extendedColumnNames[length] = mColumnName;
    return extendedColumnNames;
}

这是它如何运作的一般概念。

现在问题的关键。要防止性能损失,请创建一个哈希来保存列索引。这将作为缓存。调用getString时,请检查列索引的哈希值。如果它不存在,则使用getColumnIndex获取它并缓存它。

对不起,我目前无法添加任何代码,但我在手机上,所以我稍后会尝试添加一些代码。