読者です 読者をやめる 読者になる 読者になる

IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

Custom cursor sample

AbstractCursor

AbstractCursor implements CrossProcessCursor

    protected int mPos; // index

    public final boolean moveToPosition(int position) // various methods -> moveToPosition -> onMove (check) 

    public boolean onMove(int oldPosition, int newPosition) // override method

Sample Cursor Code

package com.example.test05;

import android.database.AbstractCursor;
import android.database.Cursor;
import android.database.CursorWindow;
import android.util.Log;

import java.util.List;
import java.util.Map;

/**
 * Custom Cursor Sample
 */
public class MyCursor2 extends AbstractCursor {

    public static final int WINDOW_SIZE = 50;

    private List<Map<String, Object>> data;

    private CursorWindow window;

    public MyCursor2(List<Map<String, Object>> data) {
        this.data = data;
        window = new CursorWindow("aaa"); // fix me! (bad provider name)
    }

    @Override
    public int getCount() {
        return data.size();
    }

    @Override
    public String[] getColumnNames() {
        return new String[]{"_id", "" , ""};// fix me! (bad column names)
    }

// see android.database.DatabaseUtils#cursorFillWindow
//    public static void cursorFillWindow(final Cursor cursor,
//                                        int position, final CursorWindow window) {
    public void cursorFillWindow(final Cursor cursor,
                                        int position, final CursorWindow window) {
        if (position < 0 || position > cursor.getCount()) {
            return;
        }
        final int oldPos = cursor.getPosition();
        final int numColumns = cursor.getColumnCount();
        window.clear();
        window.setStartPosition(position);
        window.setNumColumns(numColumns);
        mPos = position;
            //if (cursor.moveToPosition(position)) {
            if (true) {
                do {
                    if (!window.allocRow()) {
                        break;
                    }
                    for (int i = 0; i < numColumns; i++) {
                        final int type = cursor.getType(i);
                        final boolean success;
                        switch (type) {
                            case Cursor.FIELD_TYPE_NULL:
                                success = window.putNull(position, i);
                                break;

                            case Cursor.FIELD_TYPE_INTEGER:
                                success = window.putLong(cursor.getLong(i), position, i);
                                break;

                            case Cursor.FIELD_TYPE_FLOAT:
                                success = window.putDouble(cursor.getDouble(i), position, i);
                                break;

                            case Cursor.FIELD_TYPE_BLOB: {
                                final byte[] value = cursor.getBlob(i);
                                success = value != null ? window.putBlob(value, position, i)
                                        : window.putNull(position, i);
                                break;
                            }

                            default: // assume value is convertible to String
                            case Cursor.FIELD_TYPE_STRING: {
                                final String value = cursor.getString(i);
                                success = value != null ? window.putString(value, position, i)
                                        : window.putNull(position, i);
                                break;
                            }
                        }
                        if (!success) {
                            window.freeLastRow();
                            break;
                        }
                    }
                    position += 1;
                //} while (cursor.moveToNext());
                    mPos++;
                } while (mPos < this.getCount() && position < window.getStartPosition() + WINDOW_SIZE);
            }
        //}
        Log.i("xxx", "window start=" + window.getStartPosition() + " numrows=" + window.getNumRows());
        //cursor.moveToPosition(oldPos);
        mPos = oldPos;
    }

    @Override
    public CursorWindow getWindow() {
        return window;
    }

    public boolean onMove(int oldPosition, int newPosition) {

        if (newPosition < 0 || newPosition > this.getCount()) {
            return false;
        }

        CursorWindow cw = this.getWindow();
        int startPos = cw.getStartPosition();
        int rows = cw.getNumRows();

        if (newPosition > startPos + rows -1) {
            // scrolling down (start position increasing)
            // size = 8  / window size = 3
            // 0, 1, 2, 3, 4, 5, 6, 7  : index
            // *
            // *  *  *
            //       *
            //       *  *  *
            //                *            5
            //                *  *  *      5 + 3 =  8 = 8  -> start = 5
            //                   *         6
            //                   *  *  *   6 + 3 =  9 > 8  -> not reading

            int sPos = startPos + rows -1 < 0 ? 0 : startPos + rows;
            if (sPos + WINDOW_SIZE <= this.getCount()) {
                cursorFillWindow(this, sPos, cw);
            }

        } else if (newPosition <= startPos) {
            // scrolling up (start position decreasing)
            // size = 8  / window size = 3
            // 0, 1, 2, 3, 4, 5, 6, 7  : index
            // *                                  not reading   0 < size - 1
            //    *                               not reading   1 < size - 1
            //       *                            reading       2 = size - 1  from 0
            //          *                         reading       3 > size - 1

            int sPos = startPos - rows < 0 ? 0 : startPos - rows;
            if (WINDOW_SIZE -1 <= startPos) {
                cursorFillWindow(this, sPos, cw);
            }
        }
        return true;
    }

    @Override
    public String getString(int i) {
        Map<String, Object> item = data.get(getPosition());

        switch (i) {
            case 0:
                return String.valueOf(item.get("id"));
            case 1:
                return (String) item.get("name");
            case 2:
                return (String) item.get("address");
            default:
                throw new RuntimeException("invalid id " + i);
        }
    }

    @Override
    public short getShort(int i) {
        return 0;
    }

    @Override
    public int getInt(int i) {
        return 0;
    }

    @Override
    public long getLong(int i) {
        return 0;
    }

    @Override
    public float getFloat(int i) {
        return 0;
    }

    @Override
    public double getDouble(int i) {
        return 0;
    }

    @Override
    public boolean isNull(int i) {
        return false;
    }

}

Log

01-17 17:40:10.786 8715-8727/com.example.test05 I/xxx: window start=50 numrows=50
01-17 17:40:11.276 8715-8726/com.example.test05 I/xxx: window start=100 numrows=50
01-17 17:40:11.586 8715-8727/com.example.test05 I/xxx: window start=150 numrows=50
01-17 17:40:11.866 8715-8726/com.example.test05 I/xxx: window start=200 numrows=50
01-17 17:40:11.896 8715-8719/com.example.test05 D/dalvikvm: GC_CONCURRENT freed 300K, 6% free 8223K/8692K, paused 3ms+4ms, total 38ms
01-17 17:40:12.106 8715-8727/com.example.test05 I/xxx: window start=250 numrows=50
01-17 17:40:12.346 8715-8726/com.example.test05 I/xxx: window start=300 numrows=50