2012-03-29 15 views
14

Tengo una matriz de números de teléfono y deseo obtener los nombres de contacto correspondientes de la base de datos de contactos.Agregar filas al Cursor manualmente

En la matriz de números de teléfono, también tengo algunos números que no se guardan antes en la base de datos de contactos. Por ejemplo;

  • 3333333 -> Tim
  • 5555555 -> Jim
  • 1111111 -> desconocido

He la matriz que contiene los números de teléfono se muestra más arriba, a saber phoneArr.

int size=phoneArr.size(); 
if(size>0){ 
     Cursor[] cursors=new Cursor[size]; 
     for(int i=0;i<size;i++){ 
      Uri contactUri1 = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneArr.get(i))); 
      cursors[i] = getContentResolver().query(contactUri1, PEOPLE_PROJECTION, null, null, " _id asc limit 1"); 
     } 
     Cursor phones=new MergeCursor(cursors); 

phones.getCount() devuelve 2 en la situación anterior. Cuando el número de teléfono no aparece en la lista de contactos, el cursor se vacía y, de alguna manera, cuando los fusiono, no contribuye en nada. Lo que quiero es tener un cursor de la siguiente manera

móviles Cursor -> {Tim, Jim, 1111111}

Creo que puedo hacer esto mediante la adición de la fila manualmente de la siguiente manera:

Uri contactUri1 = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneArr.get(i))); 
cursors[i] = getContentResolver().query(contactUri1, PEOPLE_PROJECTION, null, null, " _id asc limit 1"); 
if(cursors[i].getCount()==0) 
    // add the phone number manually to the cursor 

¿Cómo puedo lograr esto?

Aquí es el PEOPLE_PROJECTION

private static final String[] PEOPLE_PROJECTION = new String[] { 
    ContactsContract.PhoneLookup._ID, 
    ContactsContract.PhoneLookup.DISPLAY_NAME, 
    ContactsContract.PhoneLookup.NUMBER 
}; 
+0

por favor eche un vistazo a mi solución, y vota si resuelve el problema =) – elgui

+0

Revisa la respuesta que aceptaste, parece ser incorrecta de acuerdo con las funciones actualmente disponibles del SDK de Android. –

+0

Bueno, cuando acepté la respuesta, me pareció razonable. Lo revisaré cuando tenga algo de tiempo libre. – 0x5f3759df

Respuesta

43

La manera más fácil de agregar filas en un cursor es usar MatrixCursor y MergeCursor. Esas dos clases son del SDK y están aquí para resolver ese tipo de problemas.

Básicamente lo que hacemos es:

  1. Ponga las filas que desea añadir en una MatrixCusror
  2. Combinar su cursor y su matrixCursor utilizando un MergeCursor

Algo así como:

// Create a MatrixCursor filled with the rows you want to add. 
MatrixCursor matrixCursor = new MatrixCursor(new String[] { colName1, colName2 }); 
matrixCursor.addRow(new Object[] { value1, value2 }); 

// Merge your existing cursor with the matrixCursor you created. 
MergeCursor mergeCursor = new MergeCursor(new Cursor[] { matrixCursor, cursor }); 

// Use your the mergeCursor as you would use your cursor. 
+0

¿Pondría esto en la parte superior del método bindView? –

+0

Creo que es mejor hacer esto antes de pasar el cursor al adaptador. Justo después de hacer la consulta. –

+4

agrega lo que sería el 'índice' de esta nueva fila en' mergeCursor'? – Nezam

1

Por desgracia, en la medida que yo sepa, no hay manera de que se puede añadir manualmente los datos para el cursor. Necesitas manejar esto de una manera diferente.

La única manera que puedo pensar en que puede hacerlo es

  • hacer una estructura con los campos de datos que necesita.
  • Crea un Arraylist y rellena los objetos de tu estructura con los datos de los cursores y agrégalos a la lista.
  • Ahora agregue manualmente la información de su número que falta y agréguela a la lista.
  • Pase esta lista a su adaptador, en caso de que esté pasando el cursor a un adaptador ahora. Por supuesto, debería cambiar su implementación de cursoradapter a arrayadapter.
+0

Bueno, esto no es lo que quiero escuchar :) De todos modos, gracias por responder – 0x5f3759df

+0

Ya lo sé. Es un gran dolor He maldecido mucho porque me enfrenté a esto muchas veces. Sin embargo, si logras encontrar una manera de agregar al cursor (lo que realmente dudo), comparte en esta publicación. Y como alternativa, podrías usar este método. – Shubhayu

+1

por favor eche un vistazo a mi solución, puede resolver el problema =) – elgui

2

Conozco esta publicación anterior, pero es un verdadero dolor que las filas no se puedan agregar manualmente a un Cursor. He encontrado una solución cruda. Puede ser de alguna ayuda.

Cursor es en realidad un interface y se puede crear una costumbre que classimplements la interfaz Cursor.

class ManualCursor implements Cursor{ 
     // .... 
     private Vector<String[]> rows; 

     public void addRow(String[] values){ 
      rows.add(values); 
     } 

     // Implement the necessary methods, getString(int), etc. 

     //.... 
} 

Y, finalmente, en su código

if (cursors[i].getCount() == 0){ 
    cursors[i] = new ManualCursor(); 
    cursors[i].addRow(rowValues); 
} 

Eso debería hacerlo.Pero tenga en cuenta, para que esto funcione, debe ser prudente al implementar la interfaz Cursor.

3

Utilizo una solución que hace el truco para todas mis diferentes necesidades, y que es más simple que la implementación del Cursor.
Aquí hay un ejemplo en el que tengo que agregar filas adicionales de "lista de reproducción" a un Cursor, recuperadas de Mediastore. Puedo añadir filas a primeros índices del cursor originales:

public class CursorWithExtraPlaylists extends CursorWrapper { 

public static final int ID_COLUMN_INDEX = 0; 
public static final int NAME_COLUMN_INDEX = 1; 

private int mPos = -1; 
private Context mContext; 
private Playlist[] extras; 

public CursorWithExtraPlaylists(Cursor cursor, Context context, 
     Playlist[] extras) { 
    super(cursor); 
    mContext = context; 
    this.extras = extras; 
} 

@Override 
public int getCount() { 
    return super.getCount() + extras.length; 
} 

@Override 
public int getPosition() { 
    return mPos; 
} 

@Override 
public boolean moveToFirst() { 
    return moveToPosition(0); 
} 

@Override 
public boolean moveToLast() { 
    return moveToPosition(getCount() - extras.length); 
} 

@Override 
public boolean move(int offset) { 
    return moveToPosition(mPos + offset); 
} 

@Override 
public boolean moveToPosition(int position) { 
    // Make sure position isn't past the end of the cursor 
    final int count = getCount(); 
    if (position >= count) { 
     mPos = count; 
     return false; 
    } 
    // Make sure position isn't before the beginning of the cursor 
    if (position < 0) { 
     mPos = -1; 
     return false; 
    } 
    // Check for no-op moves, and skip the rest of the work for them 
    if (position == mPos) { 
     return true; 
    } 

    mPos = position; 
    if (mPos > 0) { 
     // ok, that concerns super cursor 
     return super.moveToPosition(mPos - 1); 
    } 
    return true; 
} 

@Override 
public boolean moveToNext() { 
    return moveToPosition(mPos + 1); 
} 

@Override 
public boolean moveToPrevious() { 
    return moveToPosition(mPos - 1); 
} 

private boolean isPointingOnExtras() { 
    if (-1 == mPos || getCount() == mPos) { 
     throw new CursorIndexOutOfBoundsException(mPos, getCount()); 
    } 
    if (mPos <= extras.length - 1) { 
     // this is a request on an extra value 
     return true; 
    } 
    return false; 
} 

private Object getExtraValue(int columnIndex) { 
    switch (columnIndex) { 
    case ID_COLUMN_INDEX: 
     return extras[mPos].getId(); 
    case NAME_COLUMN_INDEX: 
     return extras[mPos].getName(mContext); 
    } 
    return null; 
} 

@Override 
public int getInt(int columnIndex) { 
    if (isPointingOnExtras()) 
     return (Integer) getExtraValue(columnIndex); 
    int res = super.getInt(columnIndex); 
    return res; 
} 

@Override 
public String getString(int columnIndex) { 

    if (isPointingOnExtras()) 
     return getExtraValue(columnIndex).toString(); 
    return super.getString(columnIndex); 
} 

public static class Playlist { 
    private int mId; 
    private int mNameResId; 

    public Playlist(int mId, int nameResId) { 
     this.mId = mId; 
     this.mNameResId = nameResId; 
    } 

    public int getId() { 
     return mId; 
    } 

    public String getName(Context mContext) { 
     return mContext.getResources().getString(mNameResId); 
    } 

} 
} 

cursor original tiene 2 columnas (int, String), por lo que construirlo con una serie de objetos filas adicionales.

+1

esto es increíble ... muchas gracias – amithgc

Cuestiones relacionadas