6

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

getColumnIndex()我想创建自己的光标,以便我可以getString()用一种方法来做。像这样的东西:

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

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

4

5 回答 5

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;
}
于 2014-11-10T13:09:19.783 回答
3

创建您自己的 getString 将导致对每个调用进行映射查找,而不仅仅是 getColumnIndex。

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

于 2011-04-12T19:02:46.283 回答
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 的重点:如果你在循环中调用它,你正在为明显的性能影响做好准备。首选方法是查找索引一次,缓存它,然后使用它。

于 2011-04-12T18:31:15.320 回答
0

您应该使用 Android SDK 中已有的DatabaseUtils .stringForQuery() 静态方法来轻松检索值,此示例适用于String机器人,还有用于Long

stringForQuery(SQLiteDatabase db, String query, String[] selectionArgs)

在数据库上运行查询并返回第一行第一列中的值的实用方法。

就像是

String myString=DatabaseUtils.stringForQuery(getDB(),query,selectionArgs);
于 2011-04-12T18:29:58.427 回答
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 获取它并缓存它。

抱歉,我目前无法添加任何代码,但我在移动设备上,所以我稍后会尝试添加一些。

于 2014-09-28T12:54:11.620 回答