2013-10-04 16 views
2

我有一個自定義的遊標適配器,並且我想將光標的每個「行」傳遞迴應用程序(通過註冊的回調正在工作)。如何克隆或凍結Android數據庫光標

我知道我可以讀取光標中的每個字段並手動執行,但我只是想將光標的「凍結克隆」傳遞回來。 (讀取適配器中的字段將需要我製作這個類的幾個專用版本。)

理想情況下,我想回傳一些與Cursor具有相同接口但不能遍歷結果集的東西。

查詢返回的行少於20行,所以空間不是問題。

+0

你什麼冰凍克隆意思? –

+0

@ M-WaJeEh我想要一個對象,它看起來像'getInt()'的'Cursor'等,但它無法移動到結果集的其他行。 – fadedbee

+0

您可以在M-WaJeEh的答案中使用'MatrixCursor',或者您可以簡單地使用包含在您自己實現的'CursorWrapper'(您將通過回調函數)中的當前'Cursor'。爲了使'Cursor'凍結,你需要覆蓋'CursorWrapper'中的所有'moveXXX'方法,從而不做任何事情。 'CursorWrapper'也實現'Cursor'接口,所以你可以得到所有'Cursor'的方法。 – Luksprog

回答

8

我想你有一個20行的遊標,現在你想用一個只包含一行的遊標來調用一個方法20次。這裏是你如何能做到這一點:

Cursor c = ...;// contains many rows 
if(c.moveToFirst()){ 
    String[] columns = c.getColumnNames(); 
    while(!c.isAfterLast()){ 
     MatrixCursor newCursor = new MatrixCursor(columns , 1); 
     MatrixCursor.RowBuilder b = newCursor.newRow(); 
     for(String col: columns){ 
      // in case all columns are of string type. But if they are 
      // different then see my comment below 
      b.add(c.getString(c.getColumnIndex(col))); 
     } 
    // invoke your listener here with newCursor 
    } 
} 

如果列的數據類型不是字符串?

對於API> = 11:只需在for循環中調用getType()方法並使用switch語句來調用適當的get方法。

對於API < 11:運行類似於此PRAGMA table_info(my_table_name)的另一個查詢,然後只填寫Map的列名和類型,並將其用於for循環。這裏是你如何閱讀這個遊標https://stackoverflow.com/a/9354401/1112882

+0

這是一個有趣的方法 - 它是否適用於非字符串列的查詢? – fadedbee

+0

是的,它絕對有效。你所要做的就是調用適當的'get'方法。但是對於這種方法,你必須知道單元的數據類型。如果你的最小目標是11,你可以在'for'循環中調用'getType()'並添加'switch'語句。 http://developer.android.com/reference/android/database/Cursor。html#getType(int) –

+0

對於API級別<11,似乎有一種獲取列類型的方法。檢查http://stackoverflow.com/a/6298521/1112882 –

1

考慮你有一個名爲data的遊標,並且遊標有「title」和「author」列,並且這兩列都有字符串值。以下代碼顯示瞭如何將光標命名數據複製到名爲matrixCursor的遊標。

String[] PROJECTION = new String[]{"title","author"}; 
MatrixCursor matrixCursor = new MatrixCursor(PROJECTION); 
int i = data.getColumnCount(); 
if (data.moveToFirst()) { 
       do { 
       Object[] currRow = new Object[i]; 
       currRow[0] = data.getString(0); 
       currRow[1] = data.getString(1); 
       matrixCursor.addRow(currRow); 
       } while (data.moveToNext()); 
      } 
0

基於Anand's answer,這應該不必指定列名/投影工作:

public static Cursor cloneCursor(Cursor oldCursor) { 

    if (oldCursor == null) { 

     return null; 

    } 
    else { 

     /** 
     * Remember the cursor position 
     */ 
     int originalCursorPosition = oldCursor.getPosition(); 

     String[] projection = oldCursor.getColumnNames(); 
     MatrixCursor newCursor = new MatrixCursor(projection); 

     int numColumns = oldCursor.getColumnCount(); 

     while (oldCursor.moveToNext()) { 

      /** 
      * Create the new row object 
      */ 
      Object[] newRow = new Object[numColumns]; 

      /** 
      * Populate each column in the new row 
      */ 
      for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) { 

       /** 
       * Detect the field type 
       */ 
       int fieldType = oldCursor.getType(columnIndex); 

       /** 
       * Use the field type to populate the row correctly 
       */ 
       if (fieldType == Cursor.FIELD_TYPE_BLOB) { 
        newRow[columnIndex] = oldCursor.getBlob(columnIndex); 
       } 
       else if (fieldType == Cursor.FIELD_TYPE_FLOAT) { 
        newRow[columnIndex] = oldCursor.getDouble(columnIndex); 
       } 
       else if (fieldType == Cursor.FIELD_TYPE_INTEGER) { 
        newRow[columnIndex] = oldCursor.getLong(columnIndex); 
       } 
       else if (fieldType == Cursor.FIELD_TYPE_STRING) { 
        newRow[columnIndex] = oldCursor.getString(columnIndex); 
       } 
       else if (fieldType == Cursor.FIELD_TYPE_NULL) { 
        newRow[columnIndex] = null; 
       } 
       else { 
        throw new RuntimeException("Unknown fieldType (" + fieldType + ") for column" + columnIndex); 
       } 

      } 

      /** 
      * Add the new row to the new cursor 
      */ 
      newCursor.addRow(newRow); 

     } 

     /** 
     * Move both cursors to the position that oldCursor was in before this method was called 
     */ 
     oldCursor.moveToPosition(originalCursorPosition); 
     newCursor.moveToPosition(originalCursorPosition); 

     /** 
     * Return the cloned cursor 
     */ 
     return newCursor; 

    } 

} 

UPDATE

getInt(...)改爲getLong(...)

getFloat(...)改爲getDouble(...)