可定制的Cursor--MatrixCursor

http://blog.csdn.net/spare_h/article/details/6673820

ContentProvider对外共享数据的时候的query()方法是需要一个cursor的。 但是如果没有数据库,需要对外共享数据使用ContentProvider的时候怎么办? 而有一些其他方法操作也都是需要cursor的。 此时就需要MatrixCursor了。相当有趣,它相当于为你模拟了一个表。代码如下:
[java]   view plain copy print ?
  1. @Override   
  2. public Cursor query(Uri uri, String[] projection, String selection,    
  3.   
  4.    String[] selectionArgs, String sortOrder) {    
  5.   
  6.   String[] tableCursor = new String[] { "name""job""salary" };    
  7.   
  8.   MatrixCursor cursor = new MatrixCursor(tableCursor);    
  9.   
  10.   cursor.addRow(new Object[] { "1111""1111""1111" });    
  11.   
  12.   return cursor;    
  13.   
  14. }   
 
以上来自:http://www.cnblogs.com/topcoderliu/archive/2011/04/26/2029576.html

         MatrixCursor还可以对已经查询完成得到的Cursor中的数据进行在二次处理,完成对Cursor的数据过滤,代码如下:
[java]   view plain copy print ?
  1. private Cursor cursorFilter(Cursor cursor){  
  2.         MatrixCursor matrixcursor=null;  
  3.         if(cursor!=null&&cursor.getCount()>0){  
  4.             matrixcursor = new MatrixCursor(columnNames);  
  5.         while(cursor.moveToNext()){  
  6.                 for(int i=0;i<4;i++){  
  7.                     columns[i]=cursor.getString(i);  
  8.                 }  
  9.                 if(filterbyrule(columns[3],columns[2])){  
  10.                     matrixcursor.addRow(columns);  
  11.                 }  
  12.             }  
  13.               
  14.         }  
  15.         return matrixcursor;  
  16. }  
           其中,columns是用于向MatrixCursor中添加记录的数组,大小与原来Cursor的列数相等;columnNames即是原Cursor的列名数组。
 

 

Cursor 位于 android.database.Cursor类,它的设计是基于数据库服务产生的。

它有几个己知的子类,分别为:

  • AbstractCursor
  • AbstractWindowedCursor
  •  CrossProcessCursor
  •  CursorWrapper
  •  MatrixCursor
  •  MergeCursor
  •  MockCursor
  • SQLiteCursor

MatrixCursor子类的源码如下:

 

[java]   view plain copy print ?
  1. package android.database;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. /** 
  6.  * A mutable cursor implementation backed by an array of {@code Object}s. Use 
  7.  * {@link #newRow()} to add rows. Automatically expands internal capacity 
  8.  * as needed. 
  9.  * 一个通过Object数组实现的容易改变的cursor,通过newRow()增加记录。 
  10.  * 它具有根据需要自动扩容的能力 
  11.  */  
  12. public class MatrixCursor extends AbstractCursor {  
  13.   
  14.     private final String[] columnNames;  
  15.     private Object[] data;  
  16.     private int rowCount = 0;  
  17.     private final int columnCount;  
  18.   
  19.     /** 
  20.      * Constructs a new cursor with the given initial capacity. 
  21.      * 
  22.      * @param columnNames names of the columns, the ordering of which 
  23.      *  determines column ordering elsewhere in this cursor 
  24.      * @param initialCapacity in rows 
  25.      */  
  26.     public MatrixCursor(String[] columnNames, int initialCapacity) {  
  27.         this.columnNames = columnNames;  
  28.         this.columnCount = columnNames.length;  
  29.   
  30.         if (initialCapacity < 1) {  
  31.             initialCapacity = 1;  
  32.         }  
  33.   
  34.         this.data = new Object[columnCount * initialCapacity];  
  35.     }  
  36.   
  37.     /** 
  38.      * Constructs a new cursor. 
  39.      * 
  40.      * @param columnNames names of the columns, the ordering of which 
  41.      *  determines column ordering elsewhere in this cursor 
  42.      */  
  43.     public MatrixCursor(String[] columnNames) {  
  44.         this(columnNames, 16);  
  45.     }  
  46.   
  47.     /** 
  48.      * Gets value at the given column for the current row. 
  49.      */  
  50.     private Object get(int column) {  
  51.         if (column < 0 || column >= columnCount) {  
  52.             throw new CursorIndexOutOfBoundsException("Requested column: "  
  53.                     + column + ", # of columns: " +  columnCount);  
  54.         }  
  55.         if (mPos < 0) {  
  56.             throw new CursorIndexOutOfBoundsException("Before first row.");  
  57.         }  
  58.         if (mPos >= rowCount) {  
  59.             throw new CursorIndexOutOfBoundsException("After last row.");  
  60.         }  
  61.         return data[mPos * columnCount + column];  
  62.     }  
  63.   
  64.     /** 
  65.      * Adds a new row to the end and returns a builder for that row. Not safe 
  66.      * for concurrent use. 
  67.      * 
  68.      * @return builder which can be used to set the column values for the new 
  69.      *  row 
  70.      */  
  71.     public RowBuilder newRow() {  
  72.         rowCount++;  
  73.         int endIndex = rowCount * columnCount;  
  74.         ensureCapacity(endIndex);  
  75.         int start = endIndex - columnCount;  
  76.         return new RowBuilder(start, endIndex);  
  77.     }  
  78.   
  79.     /** 
  80.      * Adds a new row to the end with the given column values. Not safe 
  81.      * for concurrent use. 
  82.      * 
  83.      * @throws IllegalArgumentException if {@code columnValues.length != 
  84.      *  columnNames.length} 
  85.      * @param columnValues in the same order as the the column names specified 
  86.      *  at cursor construction time 
  87.      */  
  88.     public void addRow(Object[] columnValues) {  
  89.         if (columnValues.length != columnCount) {  
  90.             throw new IllegalArgumentException("columnNames.length = "  
  91.                     + columnCount + ", columnValues.length = "  
  92.                     + columnValues.length);  
  93.         }  
  94.   
  95.         int start = rowCount++ * columnCount;  
  96.         ensureCapacity(start + columnCount);  
  97.         System.arraycopy(columnValues, 0, data, start, columnCount);  
  98.     }  
  99.   
  100.     /** 
  101.      * Adds a new row to the end with the given column values. Not safe 
  102.      * for concurrent use. 
  103.      * 
  104.      * @throws IllegalArgumentException if {@code columnValues.size() != 
  105.      *  columnNames.length} 
  106.      * @param columnValues in the same order as the the column names specified 
  107.      *  at cursor construction time 
  108.      */  
  109.     public void addRow(Iterable<?> columnValues) {  
  110.         int start = rowCount * columnCount;  
  111.         int end = start + columnCount;  
  112.         ensureCapacity(end);  
  113.   
  114.         if (columnValues instanceof ArrayList<?>) {  
  115.             addRow((ArrayList<?>) columnValues, start);  
  116.             return;  
  117.         }  
  118.   
  119.         int current = start;  
  120.         Object[] localData = data;  
  121.         for (Object columnValue : columnValues) {  
  122.             if (current == end) {  
  123.                 // TODO: null out row?  
  124.                 throw new IllegalArgumentException(  
  125.                         "columnValues.size() > columnNames.length");  
  126.             }  
  127.             localData[current++] = columnValue;  
  128.         }  
  129.   
  130.         if (current != end) {  
  131.             // TODO: null out row?  
  132.             throw new IllegalArgumentException(  
  133.                     "columnValues.size() < columnNames.length");  
  134.         }  
  135.   
  136.         // Increase row count here in case we encounter an exception.  
  137.         rowCount++;  
  138.     }  
  139.   
  140.     /** Optimization for {@link ArrayList}. */  
  141.     private void addRow(ArrayList<?> columnValues, int start) {  
  142.         int size = columnValues.size();  
  143.         if (size != columnCount) {  
  144.             throw new IllegalArgumentException("columnNames.length = "  
  145.                     + columnCount + ", columnValues.size() = " + size);  
  146.         }  
  147.   
  148.         rowCount++;  
  149.         Object[] localData = data;  
  150.         for (int i = 0; i < size; i++) {  
  151.             localData[start + i] = columnValues.get(i);  
  152.         }  
  153.     }  
  154.   
  155.     /** Ensures that this cursor has enough capacity. */  
  156.     private void ensureCapacity(int size) {  
  157.         if (size > data.length) {  
  158.             Object[] oldData = this.data;  
  159.             int newSize = data.length * 2;  
  160.             if (newSize < size) {  
  161.                 newSize = size;  
  162.             }  
  163.             this.data = new Object[newSize];  
  164.             System.arraycopy(oldData, 0this.data, 0, oldData.length);  
  165.         }  
  166.     }  
  167.   
  168.     /** 
  169.      * Builds a row, starting from the left-most column and adding one column 
  170.      * value at a time. Follows the same ordering as the column names specified 
  171.      * at cursor construction time. 
  172.      */  
  173.     public class RowBuilder {  
  174.   
  175.         private int index;  
  176.         private final int endIndex;  
  177.   
  178.         RowBuilder(int index, int endIndex) {  
  179.             this.index = index;  
  180.             this.endIndex = endIndex;  
  181.         }  
  182.   
  183.         /** 
  184.          * Sets the next column value in this row. 
  185.          * 
  186.          * @throws CursorIndexOutOfBoundsException if you try to add too many 
  187.          *  values 
  188.          * @return this builder to support chaining 
  189.          */  
  190.         public RowBuilder add(Object columnValue) {  
  191.             if (index == endIndex) {  
  192.                 throw new CursorIndexOutOfBoundsException(  
  193.                         "No more columns left.");  
  194.             }  
  195.   
  196.             data[index++] = columnValue;  
  197.             return this;  
  198.         }  
  199.     }  
  200.   
  201.     // AbstractCursor implementation.  
  202.   
  203.     @Override  
  204.     public int getCount() {  
  205.         return rowCount;  
  206.     }  
  207.   
  208.     @Override  
  209.     public String[] getColumnNames() {  
  210.         return columnNames;  
  211.     }  
  212.   
  213.     @Override  
  214.     public String getString(int column) {  
  215.         Object value = get(column);  
  216.         if (value == nullreturn null;  
  217.         return value.toString();  
  218.     }  
  219.   
  220.     @Override  
  221.     public short getShort(int column) {  
  222.         Object value = get(column);  
  223.         if (value == nullreturn 0;  
  224.         if (value instanceof Number) return ((Number) value).shortValue();  
  225.         return Short.parseShort(value.toString());  
  226.     }  
  227.   
  228.     @Override  
  229.     public int getInt(int column) {  
  230.         Object value = get(column);  
  231.         if (value == nullreturn 0;  
  232.         if (value instanceof Number) return ((Number) value).intValue();  
  233.         return Integer.parseInt(value.toString());  
  234.     }  
  235.   
  236.     @Override  
  237.     public long getLong(int column) {  
  238.         Object value = get(column);  
  239.         if (value == nullreturn 0;  
  240.         if (value instanceof Number) return ((Number) value).longValue();  
  241.         return Long.parseLong(value.toString());  
  242.     }  
  243.   
  244.     @Override  
  245.     public float getFloat(int column) {  
  246.         Object value = get(column);  
  247.         if (value == nullreturn 0.0f;  
  248.         if (value instanceof Number) return ((Number) value).floatValue();  
  249.         return Float.parseFloat(value.toString());  
  250.     }  
  251.   
  252.     @Override  
  253.     public double getDouble(int column) {  
  254.         Object value = get(column);  
  255.         if (value == nullreturn 0.0d;  
  256.         if (value instanceof Number) return ((Number) value).doubleValue();  
  257.         return Double.parseDouble(value.toString());  
  258.     }  
  259.   
  260.     @Override  
  261.     public boolean isNull(int column) {  
  262.         return get(column) == null;  
  263.     }  
  264. }  

 

 

==================================

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长度

        其构造函数为:

 

[java]   view plain copy
  1. /** 
  2.  * Constructs a new cursor with the given initial capacity. 
  3.  * 
  4.  * @param columnNames names of the columns, the ordering of which 
  5.  *  determines column ordering elsewhere in this cursor 
  6.  * @param initialCapacity in rows 
  7.  */  
  8. public MatrixCursor(String[] columnNames, int initialCapacity) {  
  9.     this.columnNames = columnNames;  
  10.     this.columnCount = columnNames.length;  
  11.   
  12.     if (initialCapacity < 1) {  
  13.         initialCapacity = 1;  
  14.     }  
  15.   
  16.     this.data = new Object[columnCount * initialCapacity];  
  17. }  
  18.   
  19. /** 
  20.  * Constructs a new cursor. 
  21.  * 
  22.  * @param columnNames names of the columns, the ordering of which 
  23.  *  determines column ordering elsewhere in this cursor 
  24.  */  
  25. public MatrixCursor(String[] columnNames) {  
  26.     this(columnNames, 16);  
  27. }  

       其中的initialCapacity,就是指存放数据值的数组的容量。

       在前面的介绍中,我们提到数据的存储格式,这一点,我们可以从MatrixCursor如何获得某一列的值看出来:

 

[java]   view plain copy
  1. /** 
  2.      * Gets value at the given column for the current row. 
  3.      */  
  4.     private Object get(int column) {  
  5.         if (column < 0 || column >= columnCount) {  
  6.             throw new CursorIndexOutOfBoundsException("Requested column: "  
  7.                     + column + ", # of columns: " +  columnCount);  
  8.         }  
  9.         if (mPos < 0) {  
  10.             throw new CursorIndexOutOfBoundsException("Before first row.");  
  11.         }  
  12.         if (mPos >= rowCount) {  
  13.             throw new CursorIndexOutOfBoundsException("After last row.");  
  14.         }  
  15.         return data[mPos * columnCount + column];  
  16.     }  

       mPos为当前行,其获取第column 列的值为mPos * columnCount + column 。

      另外,在MatrixCursor中,定义了一个行构造器类。该类定义了某一行在data中的存放位置,由改行第一列所在位置和最后一列所在位置来定义。其中有定义了获得某一列的值的函数getString(int column),getShort(int column)等函数,大家是否会觉得这些函数名很熟悉,在基于sqlite的content provider是否经常用到?

 

[java]   view plain copy
  1.  /** 
  2.      * Builds a row, starting from the left-most column and adding one column 
  3.      * value at a time. Follows the same ordering as the column names specified 
  4.      * at cursor construction time. 
  5.      */  
  6.     public class RowBuilder {  
  7.   
  8.         private int index;  
  9.         private final int endIndex;  
  10.   
  11.         RowBuilder(int index, int endIndex) {  
  12.             this.index = index;  
  13.             this.endIndex = endIndex;  
  14.         }  
  15.   
  16.         /** 
  17.          * Sets the next column value in this row. 
  18.          * 
  19.          * @throws CursorIndexOutOfBoundsException if you try to add too many 
  20.          *  values 
  21.          * @return this builder to support chaining 
  22.          */  
  23.         public RowBuilder add(Object columnValue) {  
  24.             if (index == endIndex) {  
  25.                 throw new CursorIndexOutOfBoundsException(  
  26.                         "No more columns left.");  
  27.             }  
  28.   
  29.             data[index++] = columnValue;  
  30.             return this;  
  31.         }  
  32.     }  
  33.   
  34.     // AbstractCursor implementation.  
  35.   
  36.     @Override  
  37.     public int getCount() {  
  38.         return rowCount;  
  39.     }  
  40.   
  41.     @Override  
  42.     public String[] getColumnNames() {  
  43.         return columnNames;  
  44.     }  
  45.   
  46.     @Override  
  47.     public String getString(int column) {  
  48.         Object value = get(column);  
  49.         if (value == nullreturn null;  
  50.         return value.toString();  
  51.     }  
  52.   
  53.     @Override  
  54.     public short getShort(int column) {  
  55.         Object value = get(column);  
  56.         if (value == nullreturn 0;  
  57.         if (value instanceof Number) return ((Number) value).shortValue();  
  58.         return Short.parseShort(value.toString());  
  59.     }  
  60.   
  61.     @Override  
  62.     public int getInt(int column) {  
  63.         Object value = get(column);  
  64.         if (value == nullreturn 0;  
  65.         if (value instanceof Number) return ((Number) value).intValue();  
  66.         return Integer.parseInt(value.toString());  
  67.     }  
  68.   
  69.     @Override  
  70.     public long getLong(int column) {  
  71.         Object value = get(column);  
  72.         if (value == nullreturn 0;  
  73.         if (value instanceof Number) return ((Number) value).longValue();  
  74.         return Long.parseLong(value.toString());  
  75.     }  
  76.   
  77.     @Override  
  78.     public float getFloat(int column) {  
  79.         Object value = get(column);  
  80.         if (value == nullreturn 0.0f;  
  81.         if (value instanceof Number) return ((Number) value).floatValue();  
  82.         return Float.parseFloat(value.toString());  
  83.     }  
  84.   
  85.     @Override  
  86.     public double getDouble(int column) {  
  87.         Object value = get(column);  
  88.         if (value == nullreturn 0.0d;  
  89.         if (value instanceof Number) return ((Number) value).doubleValue();  
  90.         return Double.parseDouble(value.toString());  
  91.     }  
  92.   
  93.     @Override  
  94.     public boolean isNull(int column) {  
  95.         return get(column) == null;  
  96.     }  
  97. }  

        MatrixCursor类中还定义了如何增加行的函数:

 

[java]   view plain copy
  1. /** 
  2.      * Adds a new row to the end and returns a builder for that row. Not safe 
  3.      * for concurrent use. 
  4.      * 
  5.      * @return builder which can be used to set the column values for the new 
  6.      *  row 
  7.      */  
  8.     public RowBuilder newRow() {  
  9.         rowCount++;  
  10.         int endIndex = rowCount * columnCount;  
  11.         ensureCapacity(endIndex);  
  12.         int start = endIndex - columnCount;  
  13.         return new RowBuilder(start, endIndex);  
  14.     }  
  15.   
  16.     /** 
  17.      * Adds a new row to the end with the given column values. Not safe 
  18.      * for concurrent use. 
  19.      * 
  20.      * @throws IllegalArgumentException if {@code columnValues.length != 
  21.      *  columnNames.length} 
  22.      * @param columnValues in the same order as the the column names specified 
  23.      *  at cursor construction time 
  24.      */  
  25.     public void addRow(Object[] columnValues) {  
  26.         if (columnValues.length != columnCount) {  
  27.             throw new IllegalArgumentException("columnNames.length = "  
  28.                     + columnCount + ", columnValues.length = "  
  29.                     + columnValues.length);  
  30.         }  
  31.   
  32.         int start = rowCount++ * columnCount;  
  33.         ensureCapacity(start + columnCount);  
  34.         System.arraycopy(columnValues, 0, data, start, columnCount);  
  35.     }  
  36.   
  37.     /** 
  38.      * Adds a new row to the end with the given column values. Not safe 
  39.      * for concurrent use. 
  40.      * 
  41.      * @throws IllegalArgumentException if {@code columnValues.size() != 
  42.      *  columnNames.length} 
  43.      * @param columnValues in the same order as the the column names specified 
  44.      *  at cursor construction time 
  45.      */  
  46.     public void addRow(Iterable<?> columnValues) {  
  47.         int start = rowCount * columnCount;  
  48.         int end = start + columnCount;  
  49.         ensureCapacity(end);  
  50.   
  51.         if (columnValues instanceof ArrayList<?>) {  
  52.             addRow((ArrayList<?>) columnValues, start);  
  53.             return;  
  54.         }  
  55.   
  56.         int current = start;  
  57.         Object[] localData = data;  
  58.         for (Object columnValue : columnValues) {  
  59.             if (current == end) {  
  60.                 // TODO: null out row?  
  61.                 throw new IllegalArgumentException(  
  62.                         "columnValues.size() > columnNames.length");  
  63.             }  
  64.             localData[current++] = columnValue;  
  65.         }  
  66.   
  67.         if (current != end) {  
  68.             // TODO: null out row?  
  69.             throw new IllegalArgumentException(  
  70.                     "columnValues.size() < columnNames.length");  
  71.         }  
  72.   
  73.         // Increase row count here in case we encounter an exception.  
  74.         rowCount++;  
  75.     }  
  76.   
  77.     /** Optimization for {@link ArrayList}. */  
  78.     private void addRow(ArrayList<?> columnValues, int start) {  
  79.         int size = columnValues.size();  
  80.         if (size != columnCount) {  
  81.             throw new IllegalArgumentException("columnNames.length = "  
  82.                     + columnCount + ", columnValues.size() = " + size);  
  83.         }  
  84.   
  85.         rowCount++;  
  86.         Object[] localData = data;  
  87.         for (int i = 0; i < size; i++) {  
  88.             localData[start + i] = columnValues.get(i);  
  89.         }  
  90.     }  
  91.   
  92.     /** Ensures that this cursor has enough capacity. */  
  93.     private void ensureCapacity(int size) {  
  94.         if (size > data.length) {  
  95.             Object[] oldData = this.data;  
  96.             int newSize = data.length * 2;  
  97.             if (newSize < size) {  
  98.                 newSize = size;  
  99.             }  
  100.             this.data = new Object[newSize];  
  101.             System.arraycopy(oldData, 0this.data, 0, oldData.length);  
  102.         }  
  103.     }  

         这些函数都比较简单,所以就不详细介绍了。但是需要注意一点,其中ensureCapacity函数,用于确认,当前data的容量是否已经用完了,如果用完,需要将其容量扩充为原来的两倍,这样就能存放新加入行的数据了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值