sqlite 如何克隆或冻结Android数据库游标

w46czmvw  于 2023-05-18  发布在  SQLite
关注(0)|答案(3)|浏览(170)

我有一个自定义的游标适配器,我想通过每一个'行'的光标回到应用程序(通过一个注册的回调,这是工作)。
我知道我可以从光标中读取每个字段并手动完成,但我只想将光标的“冻结克隆”传递回来。(阅读适配器中的字段需要我制作这个类的几个专门版本。)
理想情况下,我希望返回一些与Cursor具有相同接口的东西,但它不能遍历结果集。
查询返回的行少于20行,因此空间不是问题。

uelo1irk

uelo1irk1#

我猜你有一个有20行的游标,现在你想用一个只包含一行的游标调用一个方法20次。以下是您可以如何做到这一点:

Cursor c = ...;// contains many rows
if(c.moveToFirst()){
    String[] columns = c.getColumnNames();
    while(!c.isAfterLast()){ 
        MatrixCursor newCursor = new MatrixCursor(columns , 1);
        MatrixCursor.RowBuilder b = newCursor.newRow();
        for(String col: columns){
             // in case all columns are of string type. But if they are 
             // different then see my comment below 
             b.add(c.getString(c.getColumnIndex(col)));
        }
     // invoke your listener here with newCursor
    }
}

如果列的数据类型不是String怎么办?

对于API>=11:只需在for循环中调用getType()方法,并使用switch语句调用相应的get方法。
对于API<11:运行另一个类似于PRAGMA table_info(my_table_name)的查询,然后只需填写一个Map的列名和类型,并在for循环中使用它。以下是如何读取此光标https://stackoverflow.com/a/9354401/1112882

nwlqm0z1

nwlqm0z12#

假设您有一个名为data的游标,游标有“title”和“author”列,这两列都有字符串值。下面的代码显示了如何将名为data的游标复制到名为matrixCursor的游标。

String[] PROJECTION = new String[]{"title","author"};
MatrixCursor matrixCursor = new MatrixCursor(PROJECTION);
int i = data.getColumnCount();
if (data.moveToFirst()) {
                do {
                Object[] currRow = new Object[i];
                currRow[0] = data.getString(0);
                currRow[1] = data.getString(1);
                matrixCursor.addRow(currRow);
                } while (data.moveToNext());
            }
xmakbtuz

xmakbtuz3#

基于Anand's answer,这应该可以工作,而不必指定列名/投影:

public static Cursor cloneCursor(Cursor oldCursor) {

    if (oldCursor == null) {

        return null;

    }
    else {

        /**
         * Remember the cursor position
         */
        int originalCursorPosition = oldCursor.getPosition();

        String[] projection = oldCursor.getColumnNames();
        MatrixCursor newCursor = new MatrixCursor(projection);

        int numColumns = oldCursor.getColumnCount();

        while (oldCursor.moveToNext()) {

            /**
             * Create the new row object
             */
            Object[] newRow = new Object[numColumns];

            /**
             * Populate each column in the new row
             */
            for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) {

                /**
                 * Detect the field type
                 */
                int fieldType = oldCursor.getType(columnIndex);

                /**
                 * Use the field type to populate the row correctly
                 */
                if (fieldType == Cursor.FIELD_TYPE_BLOB) {
                    newRow[columnIndex] = oldCursor.getBlob(columnIndex);
                }
                else if (fieldType == Cursor.FIELD_TYPE_FLOAT) {
                    newRow[columnIndex] = oldCursor.getDouble(columnIndex);
                }
                else if (fieldType == Cursor.FIELD_TYPE_INTEGER) {
                    newRow[columnIndex] = oldCursor.getLong(columnIndex);
                }
                else if (fieldType == Cursor.FIELD_TYPE_STRING) {
                    newRow[columnIndex] = oldCursor.getString(columnIndex);
                }
                else if (fieldType == Cursor.FIELD_TYPE_NULL) {
                    newRow[columnIndex] = null;
                }
                else {
                    throw new RuntimeException("Unknown fieldType (" + fieldType + ") for column" + columnIndex);
                }

            }

            /**
             * Add the new row to the new cursor
             */
            newCursor.addRow(newRow);

        }

        /**
         * Move both cursors to the position that oldCursor was in before this method was called
         */
        oldCursor.moveToPosition(originalCursorPosition);
        newCursor.moveToPosition(originalCursorPosition);

        /**
         * Return the cloned cursor
         */
        return newCursor;

    }

}

更新

getInt(...)更改为getLong(...)
getFloat(...)变更为getDouble(...)

相关问题