Android basics 08: Android matrixcursor source code parsing

Source: Internet
Author: User

In the previous article, we gave a detailed introduction to the content provider basics. The content providers described in this article are all based on SQLite, but actually content providers can be based on other storage formats. This document introduces the XML-based content provider.
The first step is to introduce an important part of cursor. The cursor used by the XML-based content provider is different from the SQLite-based content provider. XML-based cursor must inherit the matrixcursor class. This article first introduces the matrixcursor class.
The matrixcursor class is located in the Android. database package. Four variables are defined to store related values. The introduction is as follows:
Private final string [] columnnames; column names
Private object [] data;
Store data values. Here, I usually think that we should use a table (two-dimensional array to store data values), but in fact we use a one-dimensional array to simulate two-dimensional arrays. Therefore, for a two-dimensional array:

Its format stored in data is

Private int rowcount = 0;

The number of data rows in matrixcursor. Therefore, it is easy to understand that the length of the data array must be greater than or equal to (columncount * rowcount );

Private Final int columncount;

Number of columns = columnnames Length

Its constructor is:

    /**     * Constructs a new cursor with the given initial capacity.     *     * @param columnNames names of the columns, the ordering of which     *  determines column ordering elsewhere in this cursor     * @param initialCapacity in rows     */    public MatrixCursor(String[] columnNames, int initialCapacity) {        this.columnNames = columnNames;        this.columnCount = columnNames.length;        if (initialCapacity < 1) {            initialCapacity = 1;        }        this.data = new Object[columnCount * initialCapacity];    }    /**     * Constructs a new cursor.     *     * @param columnNames names of the columns, the ordering of which     *  determines column ordering elsewhere in this cursor     */    public MatrixCursor(String[] columnNames) {        this(columnNames, 16);    }

Initialcapacity refers to the capacity of the array that stores data values.

In the previous introduction, we mentioned the data storage format. We can see from how matrixcursor obtains the values of a column:

/**     * Gets value at the given column for the current row.     */    private Object get(int column) {        if (column < 0 || column >= columnCount) {            throw new CursorIndexOutOfBoundsException("Requested column: "                    + column + ", # of columns: " +  columnCount);        }        if (mPos < 0) {            throw new CursorIndexOutOfBoundsException("Before first row.");        }        if (mPos >= rowCount) {            throw new CursorIndexOutOfBoundsException("After last row.");        }        return data[mPos * columnCount + column];    }

MPOs is the current row, and the value of the Column Retrieved is MPOs * columncount + column.

In addition, a row constructor class is defined in matrixcursor. This class defines the storage location of a row in data, which is defined by the location of the first and last columns of the modified row. The getstring (INT column), getshort (INT column), and other functions that define the values of a column are well known, is SQLite-based content provider frequently used?

 /**     * Builds a row, starting from the left-most column and adding one column     * value at a time. Follows the same ordering as the column names specified     * at cursor construction time.     */    public class RowBuilder {        private int index;        private final int endIndex;        RowBuilder(int index, int endIndex) {            this.index = index;            this.endIndex = endIndex;        }        /**         * Sets the next column value in this row.         *         * @throws CursorIndexOutOfBoundsException if you try to add too many         *  values         * @return this builder to support chaining         */        public RowBuilder add(Object columnValue) {            if (index == endIndex) {                throw new CursorIndexOutOfBoundsException(                        "No more columns left.");            }            data[index++] = columnValue;            return this;        }    }    // AbstractCursor implementation.    @Override    public int getCount() {        return rowCount;    }    @Override    public String[] getColumnNames() {        return columnNames;    }    @Override    public String getString(int column) {        Object value = get(column);        if (value == null) return null;        return value.toString();    }    @Override    public short getShort(int column) {        Object value = get(column);        if (value == null) return 0;        if (value instanceof Number) return ((Number) value).shortValue();        return Short.parseShort(value.toString());    }    @Override    public int getInt(int column) {        Object value = get(column);        if (value == null) return 0;        if (value instanceof Number) return ((Number) value).intValue();        return Integer.parseInt(value.toString());    }    @Override    public long getLong(int column) {        Object value = get(column);        if (value == null) return 0;        if (value instanceof Number) return ((Number) value).longValue();        return Long.parseLong(value.toString());    }    @Override    public float getFloat(int column) {        Object value = get(column);        if (value == null) return 0.0f;        if (value instanceof Number) return ((Number) value).floatValue();        return Float.parseFloat(value.toString());    }    @Override    public double getDouble(int column) {        Object value = get(column);        if (value == null) return 0.0d;        if (value instanceof Number) return ((Number) value).doubleValue();        return Double.parseDouble(value.toString());    }    @Override    public boolean isNull(int column) {        return get(column) == null;    }}

The matrixcursor class also defines how to add a row function:

/**     * Adds a new row to the end and returns a builder for that row. Not safe     * for concurrent use.     *     * @return builder which can be used to set the column values for the new     *  row     */    public RowBuilder newRow() {        rowCount++;        int endIndex = rowCount * columnCount;        ensureCapacity(endIndex);        int start = endIndex - columnCount;        return new RowBuilder(start, endIndex);    }    /**     * Adds a new row to the end with the given column values. Not safe     * for concurrent use.     *     * @throws IllegalArgumentException if {@code columnValues.length !=     *  columnNames.length}     * @param columnValues in the same order as the the column names specified     *  at cursor construction time     */    public void addRow(Object[] columnValues) {        if (columnValues.length != columnCount) {            throw new IllegalArgumentException("columnNames.length = "                    + columnCount + ", columnValues.length = "                    + columnValues.length);        }        int start = rowCount++ * columnCount;        ensureCapacity(start + columnCount);        System.arraycopy(columnValues, 0, data, start, columnCount);    }    /**     * Adds a new row to the end with the given column values. Not safe     * for concurrent use.     *     * @throws IllegalArgumentException if {@code columnValues.size() !=     *  columnNames.length}     * @param columnValues in the same order as the the column names specified     *  at cursor construction time     */    public void addRow(Iterable<?> columnValues) {        int start = rowCount * columnCount;        int end = start + columnCount;        ensureCapacity(end);        if (columnValues instanceof ArrayList<?>) {            addRow((ArrayList<?>) columnValues, start);            return;        }        int current = start;        Object[] localData = data;        for (Object columnValue : columnValues) {            if (current == end) {                // TODO: null out row?                throw new IllegalArgumentException(                        "columnValues.size() > columnNames.length");            }            localData[current++] = columnValue;        }        if (current != end) {            // TODO: null out row?            throw new IllegalArgumentException(                    "columnValues.size() < columnNames.length");        }        // Increase row count here in case we encounter an exception.        rowCount++;    }    /** Optimization for {@link ArrayList}. */    private void addRow(ArrayList<?> columnValues, int start) {        int size = columnValues.size();        if (size != columnCount) {            throw new IllegalArgumentException("columnNames.length = "                    + columnCount + ", columnValues.size() = " + size);        }        rowCount++;        Object[] localData = data;        for (int i = 0; i < size; i++) {            localData[start + i] = columnValues.get(i);        }    }    /** Ensures that this cursor has enough capacity. */    private void ensureCapacity(int size) {        if (size > data.length) {            Object[] oldData = this.data;            int newSize = data.length * 2;            if (newSize < size) {                newSize = size;            }            this.data = new Object[newSize];            System.arraycopy(oldData, 0, this.data, 0, oldData.length);        }    }

These functions are relatively simple, so we will not detail them in detail. Note that the ensurecapacity function is used to check whether the current data capacity is used up. If it is used up, you need to double the original capacity, in this way, you can store the data of newly added rows.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.