Добавление строк в Курсор вручную - PullRequest
17 голосов
/ 29 марта 2012

У меня есть массив телефонных номеров, и я хочу получить соответствующие имена контактов из базы данных контактов.

В массиве телефонных номеров у меня также есть номера, которые ранее не сохранялись в базе данных контактов. Например;

  • 3333333 -> Тим
  • 5555555 -> Джим
  • 1111111 -> неизвестно

У меня есть массив, содержащий номера телефонов, показанные выше, а именно 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 () возвращает 2 в приведенном выше сценарии. Когда номер телефона не отображается в списке контактов, курсор становится пустым, и когда я их объединяю, он вообще ничего не вносит. Я хочу, чтобы курсор был следующим:

Курсорные телефоны -> {Тим, Джим, 1111111}

Я думаю, что могу сделать это, добавив строку вручную следующим образом:

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

Как мне этого добиться?

Вот ЛЮДИ_ПРОЕКТА

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

Ответы [ 4 ]

51 голосов
/ 08 мая 2013

Самый простой способ добавить строки в курсоре - это использовать MatrixCursor и MergeCursor . Эти два класса взяты из SDK и предназначены для решения подобных проблем.

В основном то, что вы делаете:

  1. Поместите строки, которые вы хотите добавить в MatrixCusror
  2. Объедините ваш cursor и ваш matrixCursor, используя MergeCursor

Что-то вроде:

// 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.
3 голосов
/ 28 января 2013

Я использую решение, которое подходит для всех моих различных потребностей и которое проще, чем реализация Cursor.
Вот пример, где я должен добавить дополнительные строки «списка воспроизведения» в Курсор, полученный из Mediastore. Я добавляю строки в первые индексы оригинального курсора:

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);
    }

}
}

Исходный курсор имеет 2 столбца (int, String), поэтому я создаю его с массивом дополнительных строк объектов.

2 голосов
/ 31 октября 2012

Я знаю это старое сообщение, но очень жаль, что строки не могут быть добавлены в Курсор вручную. Я пришел с грубым решением. Это могло бы помочь.

Cursor на самом деле interface, и вы можете создать пользовательский class, который implements Cursor интерфейс.

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

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

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

      //....
}

И, наконец, в вашем коде

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

Это должно сделать это. Но будьте осторожны, чтобы это работало, вы должны быть мудрыми при реализации интерфейса Cursor.

1 голос
/ 29 марта 2012

К сожалению, насколько я знаю, вы не можете вручную добавить данные в курсор.Вы должны обрабатывать это по-другому.

Единственный способ, которым я могу придумать, как вы можете это сделать, - это

  • Создайте структуру с нужными полями данных.
  • Создайте Arraylist и заполните объекты вашей структуры данными из курсоров и добавьте их в список.
  • Теперь добавьте информацию о пропущенных номерах вручную и добавьте их в список.
  • Передайте этот список вашему адаптеру, если вы сейчас передаете курсор на адаптер.Конечно, вам придется изменить cursoradapter реализацию на arrayadapter.
...