http://blog.csdn.net/spare_h/article/details/6673820
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- String[] tableCursor = new String[] { "name", "job", "salary" };
- MatrixCursor cursor = new MatrixCursor(tableCursor);
- cursor.addRow(new Object[] { "1111", "1111", "1111" });
- return cursor;
- }
MatrixCursor还可以对已经查询完成得到的Cursor中的数据进行在二次处理,完成对Cursor的数据过滤,代码如下:
- private Cursor cursorFilter(Cursor cursor){
- MatrixCursor matrixcursor=null;
- if(cursor!=null&&cursor.getCount()>0){
- matrixcursor = new MatrixCursor(columnNames);
- while(cursor.moveToNext()){
- for(int i=0;i<4;i++){
- columns[i]=cursor.getString(i);
- }
- if(filterbyrule(columns[3],columns[2])){
- matrixcursor.addRow(columns);
- }
- }
- }
- return matrixcursor;
- }
Cursor 位于 android.database.Cursor类,它的设计是基于数据库服务产生的。
它有几个己知的子类,分别为:
- AbstractCursor
- AbstractWindowedCursor
- CrossProcessCursor
- CursorWrapper
- MatrixCursor
- MergeCursor
- MockCursor
- SQLiteCursor
MatrixCursor子类的源码如下:
- package android.database;
- import java.util.ArrayList;
- /**
- * A mutable cursor implementation backed by an array of {@code Object}s. Use
- * {@link #newRow()} to add rows. Automatically expands internal capacity
- * as needed.
- * 一个通过Object数组实现的容易改变的cursor,通过newRow()增加记录。
- * 它具有根据需要自动扩容的能力
- */
- public class MatrixCursor extends AbstractCursor {
- private final String[] columnNames;
- private Object[] data;
- private int rowCount = 0;
- private final int columnCount;
- /**
- * 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);
- }
- /**
- * 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];
- }
- /**
- * 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);
- }
- }
- /**
- * 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;
- }
- }
==================================
android基础知识08:android MatrixCursor源码解析
http://blog.csdn.net/xianming01/article/details/7385522
在上一篇文章中,我们对content provider基础进行了详细的介绍。该文中介绍的content provider都是基于sqlite的,但实际上content provider是可以基于其他存储格式的。本文将开始介绍基于xml的content provider。
第一步,我们先介绍一个重要的部分Cursor。基于xml的content provider所使用的Cursor与基于sqlite的是不同的。基于xml的Cursor需要继承MatrixCursor类。本文先介绍MatrixCursor类。
MatrixCursor类位于android.database包中。其中定义了四个变量,用来存储相关的值,其介绍如下:
private final String[] columnNames; 存放列名
private Object[] data;
存放数据值。这里,我通常认为应该用一个表(二维数组来存放数据值),但实际上却是用一个一维数组来模拟二维数组。所以对于一个二维数组:
其存放在data中的格式为
private int rowCount = 0;
MatrixCursor中存放的数据行数。因此很容易理解data数组的长度必须大于等于(columnCount*rowCount );
private final int columnCount;
列数=columnNames长度
其构造函数为:
- /**
- * 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,就是指存放数据值的数组的容量。
在前面的介绍中,我们提到数据的存储格式,这一点,我们可以从MatrixCursor如何获得某一列的值看出来:
- /**
- * 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为当前行,其获取第column 列的值为mPos * columnCount + column 。
另外,在MatrixCursor中,定义了一个行构造器类。该类定义了某一行在data中的存放位置,由改行第一列所在位置和最后一列所在位置来定义。其中有定义了获得某一列的值的函数getString(int column),getShort(int column)等函数,大家是否会觉得这些函数名很熟悉,在基于sqlite的content provider是否经常用到?
- /**
- * 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;
- }
- }
MatrixCursor类中还定义了如何增加行的函数:
- /**
- * 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);
- }
- }
这些函数都比较简单,所以就不详细介绍了。但是需要注意一点,其中ensureCapacity函数,用于确认,当前data的容量是否已经用完了,如果用完,需要将其容量扩充为原来的两倍,这样就能存放新加入行的数据了。