Подтвердить что ты не робот

Как вставить дополнительные элементы в SimpleCursorAdapter или Cursor для Spinner?

У меня есть Spinner, который должен отображать список данных, полученных из базы данных. Данные возвращаются курсору из запроса, и курсор передается в spinner SimpleCursorAdapter. Он отлично работает как таковой, но я хочу вставить еще один элемент поверх этих данных. Например, счетчик уже показывает список созданных пользователем шаблонов, сохраненных в БД, но я хочу вставить "Новый шаблон" и "Пустой шаблон" поверх списка шаблонов, и его необходимо вставить в Cursor/SimpleCursorAdapter каким-то образом.

Я рассмотрел использование arraylist и заполнение arraylist курсором, но курсор - лучшее решение для меня, так как оно содержит другие связанные строки данных. Я искал интернет для других решений и нашел некоторые ответы, предлагая использовать CursorWrapper для этой цели, но я не смог найти конкретный пример того, как использовать CursorWrapper для выполнения того, что я хочу. Как я могу вставить некоторые строки в курсор, или кто-то, пожалуйста, дайте простой пример CursorWrapper! Спасибо заранее.

4b9b3361

Ответ 1

Вы можете использовать комбинацию MergeCursor и MatrixCursor с вашим DB cursor следующим образом:

MatrixCursor extras = new MatrixCursor(new String[] { "_id", "title" });
extras.addRow(new String[] { "-1", "New Template" });
extras.addRow(new String[] { "-2", "Empty Template" });
Cursor[] cursors = { extras, cursor };
Cursor extendedCursor = new MergeCursor(cursors);

Ответ 2

Это метод, который я пробовал.

MatrixCursor m = new MatrixCursor(c.getColumnNames());
Cursor c = DBHelper.rawQuery("Select values from your_table");
MatrixCursor m = new MatrixCursor(c.getColumnNames());

//Use MatrixCursor#addRow here to add before the original cursor

while (c.moveToNext()) {
    //Use MatrixCursor#addRow here to add before the original row
    DBHelper.insertRow(c, m);
    //Use MatrixCursor#addRow here to add after the original row

}
//Use MatrixCursor#addRow here to add after the original cursor

m.addRow(new String[]{col1Val, col2Val, col3Val,..., //to match the number of columns needed});

DBHelper.insertRow()

public final static void insertRow(Cursor from, MatrixCursor to) {
final String columns[] = from.getColumnNames(), values[] = new String[columns.length];
    final int size = columns.length;

    for (int i = 0; i < size; i++) {
        values[i] = getStringFromColumn(from, columns[i]);
    }
    to.addRow(values);
}

С помощью этого метода вы можете добавить любое количество строк в любом месте вашего курсора. Несмотря на то, что он не использует CursorWrapper, его можно использовать с CursorAdapters или SimpleCursorAdapters.

Ответ 3

Я попробовал решение, предоставленное @naktinis, но результат не был тем, что я ожидал. То, что я сам хотел достичь в качестве адаптера, в который можно добавить новые элементы вверху (индекс 0). Однако с учетом данного решения новые элементы были действительно добавлены сверху, но только к END MatrixCursor. Другими словами, когда я динамически добавлял строки в MatrixCursor "extras" , у меня было что-то вроде этого:

  • "extras" строка 1
  • "extras" строка 2
  • "extras" строка 3
  • "курсор" строка 1
  • "курсор" строка 2
  • "курсор" строка 3.

Однако то, чего я действительно хотел достичь, было примерно так:

  • "extras" строка 3
  • "extras" строка 2
  • "extras" строка 1
  • "курсор" строка 1
  • "курсор" строка 2
  • "курсор" строка 3.

Другими словами, самые последние элементы вводятся вверху (индекс 0).

Я смог добиться этого вручную, выполнив следующее. Обратите внимание, что я не включал никакой логики для динамического удаления элементов из адаптера.

private class CollectionAdapter extends ArrayAdapter<String> {

  /**
   * This is the position which getItem uses to decide whether to fetch data from the
   * DB cursor or directly from the Adapter underlying array. Specifically, any item
   * at a position lower than this offset has been added to the top of the adapter
   * dynamically.
   */
  private int mCursorOffset;

  /**
   * This is a SQLite cursor returned by a call to db.query(...).
   */
  private Cursor mCursor;

  /**
   * This stores the initial result returned by cursor.getCount().
   */
  private int mCachedCursorCount;

  public Adapter(Context context, Cursor cursor) {
    super(context, R.layout.collection_item);
    mCursor = cursor;
    mCursorOffset = 0;
    mCachedCursorCount = -1;
  }

  public void add(String item) {
    insert(item, 0);
    mCursorOffset = mCursorOffset + 1;
    notifyDataSetChanged();
  }

  @Override
  public String getItem(int position) {
    // return the item directly from underlying array if it was added dynamically.
    if (position < mCursorOffset) {
      return super.getItem(position);
    }

    // try to load a row from the cursor.
    if (!mCursor.moveToPosition(position - mCursorOffset)) {
      Log.d(TAG, "Failed to move cursor to position " + (position - mCursorOffset));
      return null; // this shouldn't happen.
    }
    return mCursor.getString(INDEX_COLLECTION_DATA);   
  }

  @Override
  public int getCount() {
    if (mCachedCursorCount == -1) {
      mCachedCursorCount = mCursor.getCount();
    }
    return mCursorOffset + mCachedCursorCount;
  }
}