androidandroid-cursormergecursor

Android: Add column to already populated Cursor


I'm confused about whether to use MergeCursor or CursorJoiner.

I have a Cursor (A) with a load of data in it. Lets say there are 100 rows in Cursor (A) and 3 columns. What I want to do is insert (append) a new column to the Cursor so the resulting Cursor (B) has 100 rows but 4 columns.

At this moment in time I would like the 4th column to contain a default value for the 100 rows.

How would I do this?


Solution

  • You can use the Decorator pattern here.

    For this, Android has CursorWrapper , which is a...

    Wrapper class for Cursor that delegates all calls to the actual cursor object. The primary use for this class is to extend a cursor while overriding only a subset of its methods.

    Suppose your new column is called newColumn, and that it is of type String then you can do something along these lines:

    class MyCursorWrapper extends CursorWrapper {
        private final String NEW_COLUMN = "newColumn";
    
        @Override
        public int getColumnCount() {
            // Count the virtual column in
            return getWrappedCursor().getColumnCount() + 1;
        }
    
        @Override
        public int getColumnIndex(String columnName) {
            // Return the virtual column if they are asking for it,
            // otherwise just use the original 
            if (columnName != null && columnName.equals("newColumn") {
                return getWrappedCursor().getColumnCount();
            }
            return mCursor.getColumnIndex(columnName);
        }
    
        public int getColumnIndexOrThrow(String columnName)
                throws IllegalArgumentException {
            // Same logic as getColumnIndex()
            if (columnName != null && columnName.equals(NEW_COLUMN) {
                return getWrappedCursor().getColumnCount();
            }
            return getWrappedCursor.getColumnIndexOrThrow(columnName);
        }
    
        @Override
        public String getColumnName(int columnIndex) {
             if (columnIndex == getWrappedCursor.getColumnCount()) {
                 return NEW_COLUMN;
             }
             return getWrappedCursor().getColumnName(columnIndex);
        }
    
        @Override
        public String[] getColumnNames() {
            // Add our virtual column to the result from the original Cursor
            String original = getWrappedCursor().getColumnNames()
            String result = new String[original.length + 1];
            System.arrayCopy(original, 0, result, 0, original.length);
            result[original.length] = NEW_COLUMN;
            return result;
        }
    
        @Override
        public String getString(int columnIndex) {
            // For the last column, return whatever you need to return here
            // For real columns, just delegate to the original Cursor
            if (columnIndex == getWrappedCursor().getColumnCount()) {
                return yourResultHere();
            }
            return getWrappedCursor().getString(columnIndex);
        }
    }