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

Набор данных изменения RecyclerView

Я хочу реализовать функцию поиска для моего RecyclerView. При изменении текста я хочу изменить данные, отображаемые с помощью этого виджета. Возможно, этот вопрос задан раньше или прост, но я не знаю, как изменить данные, которые должны отображаться...

My RecyclerView определяется следующим образом:

     // 1. get a reference to recyclerView
    mRecyclerView = (RecyclerView)findViewById(R.id.recyclerView);

    // 2. set layoutManger
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    // 3. create an adapter
    mAdapter = new ItemsAdapter(itemsData);
    // 4. set adapter
    mRecyclerView.setAdapter(mAdapter);

И данные, которые я показываю, это что-то вроде:

   ItemData itemsData[] = { new ItemData("Mary Richards"),
        new ItemData("Tom Brown"),
        new ItemData("Lucy London")          
};

Итак, когда я хочу предоставить адаптеру другой набор данных, другой массив (например, с одним элементом), что мне делать?

4b9b3361

Ответ 1

Если у вас есть устойчивые идентификаторы в вашем адаптере, вы можете получить довольно хорошие результаты (анимации), если вы создадите новый массив, содержащий отфильтрованные элементы, и вызовите

recyclerView.swapAdapter(newAdapter, false);

Используя swapAdapter, подсказки RecyclerView позволяют повторно использовать держатели. (vs в setAdapter, он должен перерабатывать все представления и воссоздавать, потому что он не знает, что новый адаптер имеет тот же ViewHolder, что и старый адаптер).

Лучшим подходом было бы найти, какие элементы удаляются и вызывать notifyItemRemoved(index). Не забудьте удалить элемент. Это позволит RecyclerView запускать прогностическую анимацию. Предполагая, что у вас есть адаптер, который внутренне использует ArrayList, реализация будет выглядеть так:

// adapter code
final List<ItemData> mItems = new ArrayList(); //contains your items
public void filterOut(String filter) {
   final int size = mItems.size();
   for(int i = size - 1; i>= 0; i--) {
       if (mItems.get(i).test(filter) == false) {
           mItems.remove(i);
           notifyItemRemoved(i);
       }
   }
}

Он будет работать еще лучше, если вы можете выполнять вызовы notifyItemRemoved и использовать notifyItemRangeRemoved. Он выглядел бы так: (не тестировалось)

public void filterOut(String filter) {
   final int size = mItems.size();
   int batchCount = 0; // continuous # of items that are being removed
   for(int i = size - 1; i>= 0; i--) {
       if (mItems.get(i).test(filter) == false) {
           mItems.remove(i);
           batchCount ++;
       } else if (batchCount != 0) { // dispatch batch
           notifyItemRangeRemoved(i + 1, batchCount);
           batchCount = 0;
       }
   }
   // notify for remaining
   if (batchCount != 0) { // dispatch remaining
       notifyItemRangeRemoved(0, batchCount);
   }
}

Вам нужно расширить этот код, чтобы добавить элементы, которые ранее были отфильтрованы, но теперь должны быть видимыми (например, пользователь удаляет запрос фильтра), но я думаю, что это должно дать основную идею.

Имейте в виду, что каждый из уведомлений о вызове элемента влияет на те, которые после него (вот почему я просматриваю список из конца, чтобы избежать его). Переход от конца также помогает ArrayList удалять производительность метода (меньше элементов для смены).

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

notifyItemRangeRemoved(0, 2); // 2 items starting from index 0

или если вы отправляете их по одному

notifyItemRemoved(0);
notifyItemRemoved(0);//because after the previous one is removed, this item is at position 0

Ответ 2

Это мой ответ - благодаря Ивану Скоричу с его сайта: http://blog.lovelyhq.com/creating-lists-with-recyclerview-in-android/

Я создал дополнительный метод внутри моего класса адаптера:

public void updateList(List<Data> data) {
    mData = data;
    notifyDataSetChanged();
}

Затем каждый раз, когда ваши данные изменяются, вы просто вызываете этот метод, передавая ваши новые данные, и ваше представление должно измениться, чтобы отразить его.

Ответ 3

Просто заново инициализируйте адаптер:

mAdapter = new ItemsAdapter (newItemsData);

или если вам нужно удалить только несколько отдельных элементов, а не весь список:

mAdapter. notifyItemInserted (положение);

или

mAdapter.notiftyItemRemoved(положение);

Ответ 4

Как ответил ygit, swapAdapter интересен, когда вам нужно изменить весь контент.

Но в моем FlexibleAdapter вы можете обновлять элементы с помощью updateDataSet. Вы даже можете настроить адаптер для вызова notifyDataSetChanged или иметь анимацию синхронизации (по умолчанию включена). Это потому, что notifyDataSetChanged убивает все анимации, но это хорошо для больших списков.

Пожалуйста, просмотрите страницы описания, demoApp и Wiki: https://github.com/davideas/FlexibleAdapter