How to clone or freeze an Android database cursor

I have a custom cursor adapter, and I would like to pass each "line" of the cursor back to the application (via a registered callback that works).

I know that I can read each of the fields from the cursor and do it manually, but I just would like to pass the "frozen clone" of the cursor. (Reading the fields in the adapter will require me to create several specialized versions of this class.)

Ideally, I would like to pass something with the same interface as Cursor, but which could not pass the result set.

Queries return less than 20 rows, so space is not a problem.

+2
source share
3 answers

I assume that you have a pointer to 20 lines, and now you want to call the method 20 times with a cursor that contains only one line. Here's how you can do it:

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 the column data type is not a row?

For API> = 11: just call the method getType()in a loop forand use the statement switchto call the corresponding get method.

For API <11: Run another query like this PRAGMA table_info(my_table_name), and then just fill in Mapthe column name and enter it and use in the for loop. Here is how you can read this cursor fooobar.com/questions/657143 / ...

+8
source

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());
            }
+1

Based on Anand's answer, this should work without specifying column / projection names:

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

0
source

Source: https://habr.com/ru/post/1657605/


All Articles