приклад notifyDataSetChanged


166

Я намагаюся використовувати в моєму Android Applicationдо notifyDataSetChanged()для методу , ArrayAdapterале він не працює для мене.

Тут я знайшов відповідь , що вона notifyDataSetChanged()повинна працювати в основній темі, але прикладу для цього не було.

Хтось може надіслати приклад або хоча б посилання ?!



ви можете перевірити цей блог та цей приклад в github, а також це
Cabezas

Відповіді:


328

Для того ArrayAdapter, notifyDataSetChangedпрацює тільки якщо ви використовуєте add(), insert(), remove(), і clear()на адаптері.

Коли ArrayAdapterконструкція побудована, вона містить посилання на те, Listщо було передано. Якщо ви повинні перейти до а, Listякий був учасником діяльності, і змінити цього учасника діяльності пізніше, ArrayAdapterвін все ще містить посилання на оригінал List. Адаптер не знає, що ви змінили Listактивність.

Ваш вибір:

  1. Використовуйте Функції ArrayAdapterзмінити основний список ( add(), insert(), remove(), clear()і т.д.)
  2. Заново створіть ArrayAdapterнові Listдані. (Використовується багато ресурсів та збирання сміття.)
  3. Створіть свій власний клас , похідний від BaseAdapterі , ListAdapterщо дозволяє змінювати подстилающую Listструктуру даних.
  4. Використовуйте notifyDataSetChanged()щоразу, коли список оновлюється. Для виклику на UI-тему, використовувати runOnUiThread()в Activity. Тоді, notifyDataSetChanged()буде працювати.

13
будьте обережні і при призначенні "нових" об'єктів до ваших даних. використовуйте clear () замість цього, перенаселяйте / вносіть зміни в дані, а потім зателефонуйте notifyDataSetChanged ()
moonlightcheese

Але що робити, якщо ми закликаємо notifyDataSetChanged()таким чином ((BaseAdapter) arrayAdapter).notifyDataSetChanged();:?
teoREtik

2
Я використовую BaseExpandableListAdapter, він не має функцій add () або delete (), тому я зберігаю свою Map як змінну члена. Я оновлюю Map і дзвоню notifyDatasetChanged (), але нічого не відбувається. Коли я використовую вибір №4, він працює. Чому ???
смарагдовий

Я використовую ArrayAdapter для користувацького GridView, я додаю зображення, отримуючи їх із URL-адрес, зателефонувавши на adapter.add (dataReceived). Це чудово додає дані, але чому це оновлення та перехід до вершини. Я хочу показати елементи, оскільки вони отримають додавання без оновлення списку. (Що потрібно зробити, це робота з Android GridView за допомогою notifyDatasetChanged ()) Як я можу змусити це працювати в цьому customGridView (StaggeredGridView).
MobileEvangelist

1
Я спробував створити власний BaseAdapter, щоб додати методи сортування до списку, але чомусь це просто не вийшло. Не те, що моя програма повільна, навіть якщо я відтворюю весь адаптер з відсортованим масивом, але це все одно мене дратує. Як саме це створило б багато сміття? Я припускаю, що фактичний масив дорогих даних зберігається як орієнтир у діяльності, яка викликає адаптер, тобто лише адаптер буде зібраний.
G_V

34

Можна використовувати runOnUiThread()метод наступним чином. Якщо ви не використовуєте ListActivity, просто адаптуйте код, щоб отримати посилання на свій ArrayAdapter.

final ArrayAdapter adapter = ((ArrayAdapter)getListAdapter());
runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }
});

1
Я спробував додати фрагмент коду до вас у свій код (ви можете знайти його тут stackoverflow.com/questions/3667442/how-to-refresh-adapter ) у методі onCreate, але успіху досі не маю :( Можливо, це було неправильне місце для його додавання ?!
Тіма,

1
У вашому запитанні якраз було задано питання про те, як ви могли викликати метод і запустити його в основній темі інтерфейсу. Це відповідає на це питання. У вашому конкретному випадку ( stackoverflow.com/questions/3670500 / ... ) AsyncTask і () метод його onPostExecute , здається, що ви повинні розглянути.
Брайан

12

Нещодавно я писав на цю тему, хоча цей пост старий, я думав, що це буде корисно тому, хто хоче знати, як реалізувати BaseAdapter.notifyDataSetChanged()крок за кроком і правильно.

Дотримуйтесь інструкцій Як правильно реалізувати BaseAdapter.notifyDataSetChanged () в Android або в новому блозі BaseAdapter.notifyDataSetChanged () .


Привіт, я спробував перший приклад посилання, але замість цього mItem.add()я зробив лише редагування одного елемента, наприклад, mItem.get(position).setImage(encodedImage)може бути ось чому він дає помилку exeption NullPointer. Так що notifyDataSetChange працює над його редагуванням, bcz для адаптера масиву це згадано вище, він працює лише для add (), clear (), remove () тощо
Shreekant N

notifyDataSetChanged буде працювати для редагування чи зміни набору даних, ваш нульовий вказівник через щось інше, перевірте журнали.
Аріф Надей

7

У мене була така ж проблема, і я вважаю за краще не замінювати весь ArrayAdapter новим екземпляром постійно. Таким чином, я маю AdapterHelper робити важкий підйом десь в іншому місці.

Додайте це там, де зазвичай (намагайтеся) сповістити про дзвінки

new AdapterHelper().update((ArrayAdapter)adapter, new ArrayList<Object>(yourArrayList));
adapter.notifyDataSetChanged();

Клас AdapterHelper

public class AdapterHelper {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void update(ArrayAdapter arrayAdapter, ArrayList<Object> listOfObject){
        arrayAdapter.clear();
        for (Object object : listOfObject){
            arrayAdapter.add(object);
        }
    }
}

У мене є кілька інших ArrayAdapters у своєму коді, і вони працювали без проблем. Сьогодні ввечері я вирішив перетворити SimpleCursorAdapter в ArrayAdapter, і це НЕ БУДЕ РОБОТИ. Після боротьби з ним протягом декількох годин і намагаючись знайти причину, чому це не вийде, я знайшов ваш клас AdapterHelper і ЗАРАЗ зараз працює! Дякую!
ponosgeekdad

1
Це легко зробити у функції ... ЧОМУ ви б створили новий клас для цього?
techiServices

2
У Java функції називають методами. Що б ви запропонували, чи є цей метод, який може бути повторно використаний, у тому ж класі, що і адаптер масиву? Або фрагмент / активність, що містить перегляд списку? Так так, це в класі, де його можна повторно використовувати. Якщо ви хочете зробити його статичним будь-якими способами, продовжуйте.
Кевін Паркер

1
Хороша ідея. Ще одним було б розширити ArrayAdapter, названий ArrayAdapterCompat і замінити метод addAll (..), оскільки цей доступний лише з API 11. Там же перевірте рівень API та використовуйте super.addAll(..)API> 11 та super.add (.. ) в поєднанні з итерацией , як ваші: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { super.addAll(items); } else { for (Object o : collection) { super.add(o); } }. Тепер просто продовжте свій новий клас адаптерів.
Konsumierer

Ідеально! Дякую @Kevin - це було ТОЧНО те, що мені потрібно!
Кібі

3

Я знаю, що це пізня відповідь, але я зіткнувся з подібною проблемою, і мені вдалося вирішити це, використовуючи notifyDataSetChanged()в потрібному місці.

Тож моя ситуація була така.

Мені довелося оновити перегляд списку на вкладці (фрагменті) панелі дій із вмістом, повернутим із зовсім іншої діяльності. Спочатку перегляд списку не відображав би жодних змін. Однак, коли я натиснув іншу вкладку, а потім повернувся до потрібної вкладки, перегляд списку буде оновлений правильним вмістом з іншої діяльності. Тому для вирішення цього питання я використовував notifyDataSetChanged()адаптер бар дії в коді діяльності, який повинен був повернути дані.

Це фрагмент коду, який я використовував у своїй діяльності.

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) 
    {
        case R.id.action_new_forward:

            FragmentTab2.mListAdapter.notifyDataSetChanged();//this updates the adapter in my action bar tab
            Intent ina = new Intent(getApplicationContext(), MainActivity.class);
            ina.putExtra("stra", values1);
            startActivity(ina);// This is the code to start the parent activity of my action bar tab(fragment).
    }
}

Ця активність повертає деякі дані, FragmentTab2і вона безпосередньо оновлює перегляд списку в FragmentTab2.

Сподіваюся, хтось вважає це корисним!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.