Адаптер RecyclerView notifyDataSetChanged не работает

я продлил

RecyclerView.Adapter<RecyclerView.ViewHolder>

И когда я позвонил:

mRecyclerView.getAdapter().notifyDataSetChanged();

Ничего не произошло.

Единственный способ обновить представление — снова установить адаптер (см. этот ответ) :

mRecyclerView.setAdapter(new MyAdapter(...));

У меня есть две проблемы с этим решением:

  1. Я вижу мигание на экране, когда я снова устанавливаю адаптер
  2. Список возвращается на первую позицию.

Любые идеи?


person David    schedule 30.12.2014    source источник
comment
Вы пытались инкапсулировать метод notifyDataSetChanged в MyAdapter? Например: создайте myNotifyDataSetChanged в MyAdapter и из этого метода вызовите this.notifyDataSetChanged(). Сохраните ссылку MyAdapter и вызовите myAdapterRef.myNotifyDataSetChanged() вместо myRecyiclerView.getAdapter().notifyDataSetChanged(). Не знаю, почему это сработало для меня (у меня была такая проблема с ListView)   -  person bajicdusko    schedule 31.12.2014
comment
@helionprime Не помогло :(   -  person David    schedule 31.12.2014
comment
хорошо, мой плохой. Я забыл получить/использовать обновленные данные в методе onBindViewHolder. А как же эффект мерцания, как от него избавиться?   -  person David    schedule 31.12.2014
comment
хорошо, мой bad2. Эффект мерцания, связанный с загрузкой изображения в изображения в моих элементах. Это известная проблема с UniversalImageLoader (github.com/nostra13/Android-Universal). -Image-Loader/issues/376), который я использую.   -  person David    schedule 31.12.2014
comment
Я рад, что вам удалось решить эту проблему :-). Если вы хотите попробовать избавиться от мерцания, перейдите по этой ссылке github.com/bajicdusko/AndroidJsonProvider/tree/master/app/src/ вы можете попробовать загрузчик изображений, который я разработал для себя. Он также поддерживает кэширование, оптимизацию, автозагрузку и отображение изображения по умолчанию в случае ошибок.   -  person bajicdusko    schedule 31.12.2014
comment
Удалось ли вам найти решение вашей проблемы, @David. У меня такая же проблема.   -  person Gaurav Arora    schedule 02.02.2016


Ответы (8)


Если notifyDataSetChanged() не запускает обновления представления, есть вероятность, что вы забыли вызвать SetLayoutManager() в своем RecyclerView (как я!). Только не забудьте сделать это: код Java:

LinearLayoutManager layoutManager = new LinearLayoutManager(context ,LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager)

Код C#, я использую Xamarin.

var layoutManager = new LinearLayoutManager(Context, LinearLayoutManager.Vertical, false);
recyclerView.SetLayoutManager(layoutManager);

перед тем, как позвонить recyclerView.SetAdapter(adapter);

Если вы предпочитаете объявлять его в xml, чтобы вы не могли забыть его в коде, вы также можете добавить эти строки в xml вашего recyclerView:

app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="vertical"
person Varvara Kalinina    schedule 24.10.2016

Если ваш getItemCount() возвращает 0, то notifyDataSetChanged() ничего не сделает. Убедитесь, что при инициализации адаптера вы передаете допустимый набор данных.

person IgorGanapolsky    schedule 14.10.2015

Согласно javadocs: если вы пишете адаптер, всегда будет более эффективно использовать более конкретные события изменения, если вы можете. Положитесь на notifyDataSetChanged() в крайнем случае.

public class NewsAdapter extends RecyclerView.Adapter<...> {    

private static List mFeedsList;
...

    public void swap(List list){
    if (mFeedsList != null) {
        mFeedsList.clear();
        mFeedsList.addAll(list);
    }
    else {
        mFeedsList = list;
    }
    notifyDataSetChanged();
}

Я использую Retrofit для получения списка при использовании Retrofit onResponse(),

adapter.swap(feedList);
person Akshay Goyal    schedule 24.12.2015
comment
Согласно javadocs: если вы пишете адаптер, всегда будет более эффективно использовать более конкретные события изменений, если вы можете, где в javadocs вы нашли эту информацию? - person Marian Paździoch; 12.10.2016

Чтобы обновить recyclerview, мы можем сделать следующее:

  1. Снова создайте и установите адаптер:

    adapter=new MyAdapter(...);
    mRecyclerView.setAdapter(adapter);
    
  2. Очистите данные списка моделей, а затем уведомите:

    List<YourModel> tempModel=new ArrayList<>(modelList); 
    modelList.clear();   
    modelList.addAll(tempModel); 
    adapter.notifyDataSetChanged();
    
person Mayur Prasad    schedule 02.02.2018
comment
Нет необходимости каждый раз создавать новый адаптер. Все, что вам нужно, это передать новые данные существующему адаптеру. Пожалуйста, смотрите мой рабочий пример ниже. - person akelec; 15.10.2019

В моем случае ничего, кроме этого, не сработало. Когда пришло время обновить RecyclerView, я сделал:

array = getNewItems();                    // populates the list with new items
((MyAdapter) mAdapter).setValues(array);  // pass the new list to adapter !!!
mAdapter.notifyDataSetChanged();          // tell the adapter a data set has changed

В MyAdapter я помещаю сеттер для данных:

public void setValues(List<Item> items){
    this.items = items;
}

Вот и все!

[Обратите внимание, что notifyDataSetChanged не работает без установки новых значений для адаптера.]

person akelec    schedule 15.10.2019

Хочу поделиться, столкнулся с такой же проблемой. Но то, что я делал неправильно, было. Я создавал экземпляр адаптера каждый раз, когда он был новым, а затем выполнял notifysetDatachange() для этого нового экземпляра, а не для старого.

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

     MyAdapter mAdapter = new MyAdapter(...)

    mRecyclerView.setAdapter(mAdapter );

// TODO 
mAdapter.modifyData(....);
mAdapter.notifySetDataChange();


    MyAdapter extends baseAdapter {
     MyAdapter () {
    }
    modifyData(String[] listData) {

    }

    }
person sharma_kunal    schedule 13.01.2017

notifyDataSetChanged() следует вызывать в основном потоке.

person inhogo    schedule 08.02.2017
comment
Это не похоже на проблему - person Gabriel; 04.08.2017
comment
Спасибо. Моя проблема заключалась в прослушивании службы, которая работает в другом потоке. - person David Vareka; 07.12.2020
comment
Это сработало в моем случае, спасибо - person nonabhai; 19.04.2021

Итак, я исправил свою проблему следующим образом: orderList - это список, который я передаю в recyclerview. Мы можем просто добавить элемент в позицию в списке, здесь 0 — это 0-я позиция в списке. Затем вызовите adapter.notifyDataSetChanged() . Работает как шарм

1) orderList.add(0,String); 2) orderAdapter.notifyDataSetChanged();

person Partha Sarathi Murmu    schedule 28.08.2018