Проблема с обновлением представления строки в recyclerview

Я хочу обновить представление recyclerview при вызове notifyItemChanged. Дело в том, что я не хочу обновлять всю строку, а только вид строки. (чтобы избежать эффекта мерцания строки)

Существует метод с именем notifyItemChanged(int, payload obj).

Могу ли я использовать это для достижения этого? Если да, то как это сделать?


person chathura    schedule 16.02.2016    source источник
comment
Вы уже пробовали что-нибудь? Можете ли вы показать нам какой-нибудь код, например, ваш адаптер recyclerview?   -  person hehe    schedule 16.02.2016


Ответы (3)


Наконец я нашел, как обновить только конкретное представление строки в RecyclerView.

(1) Переопределить onBindViewHolder(Recycler.ViewHolder VH, int position, List payloads) в адаптере.

(2) Внутри этого метода onBindViewHolder

if(payloads != null && !payloads.isEmpty() && (payloads.get(0) instanceof  customObject)){
   // update the specific view
}else{
   // I have already overridden  the other onBindViewHolder(ViewHolder, int)
   // The method with 3 arguments is being called before the method with 2 args. 
   // so calling super will call that method with 2 arguments. 
   super.onBindViewHolder(holder,position,payloads);
}

(3) Таким образом, чтобы уведомить об изменении данных и обновить представление, необходимо вызвать notifyItemChanged(int position, Object payload). Необходимо передать customObject (модель, которая содержит данные) в качестве объекта полезной нагрузки.

adapter.notifyItemChanged(i, obj);

Примечание. Необходимо отключить ItemAnimator RecyclerView (по умолчанию он включен). В противном случае объект полезной нагрузки будет пустым.

recyclerView.setItemAnimator(null);

or

((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

ОБНОВЛЕНИЕ: недавно я использовал этот метод, не отключая ItemAnimator. Так что нет необходимости отключать ItemAnimator. - (recyclerview-v7:25.4.0)

для дальнейшего справки

person chathura    schedule 16.02.2016
comment
Очень хорошо. Эта проблема вызвала у меня головную боль, поскольку она создавала два ViewHolder, хотя я хотел изменить только один элемент через notifiyItemChanged. - person ono; 28.01.2018
comment
Идеальный. Это то, что я хотел. - person Rhusfer; 20.05.2019

Вы можете использовать это, чтобы получить представление об обновленном элементе:

View v = recyclerView.getLayoutManager().findViewByPosition(position);
if (v != null){
    //update your view
}
person Rey Pham    schedule 16.02.2016

Допустим, у вас есть ArrayList элементов, и он передается адаптеру RecyclerView. Пусть это будет что-то вроде этого.

List<String> items = new ArrayList<>();
RecyclerAdapter adapter = new RecyclerAdapter(items);
recyclerView.setAdapter(adapter);

Теперь, как я вижу, вы хотите вставить элементы в RecyclerView и вызвать метод notifyItemChanged(int position), чтобы добавить только один элемент.

Для этого предположим, что вы изменили значение элемента в позиции 0. Это первый элемент в списке.

Теперь правильное использование метода notifyItemChanged(int position) будет

adapter.notifyItemChanged(0);

Это означает, что адаптер обновит recyclerview новым значением в позиции 0.

person capt.swag    schedule 16.02.2016
comment
не вставлять элемент. Мне нужно изменить уже существующий элемент списка массивов - person chathura; 16.02.2016
comment
Затем вместо вызова notifyItemInserted(int position) вызовите notifyItemChaged(int position). Я обновил ответ. - person capt.swag; 16.02.2016
comment
да я уже так делаю. но он обновляет всю строку, вызывая эффект мигания. Я хочу избежать этого, обновляя только конкретный вид строки. - person chathura; 16.02.2016
comment
Вы снова вызываете метод setAdapter()? - person capt.swag; 16.02.2016
comment
нет, просто измените логическое значение объекта и вызовите notifyItemChanged. Я отладил его, и он снова проходит через onBindViewHolder и снова сбрасывает данные в представления. - person chathura; 16.02.2016