How to clone or freeze an Android database cursor

三世轮回 提交于 2019-12-01 00:28:04
M-WaJeEh

I guess you have a cursor with 20 rows and now you want to invoke a method 20 times with a cursor that contains only one row. Here is how you can do this:

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

What if data type of columns is not String?

For API>=11: Just call getType() method in for loop and use switch statement to invoke appropriate get method.

For API<11: Run another query similar to this PRAGMA table_info(my_table_name) and then just fill a Map of column name and type and use it in for loop. Here is how you can read this cursor https://stackoverflow.com/a/9354401/1112882

Consider you have a cursor named data and cursor have columns "title" and "author" and both these columns have string values. The below code shows how to copy cursor named data to cursor named 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());
            }
ban-geoengineering

Based on Anand's answer, this should work without having to specify the column names / projection:

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;

    }

}

UPDATE

getInt(...) changed to getLong(...).

getFloat(...) changed to getDouble(...)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!