Вы должны запустить его в потоке пользовательского интерфейса. Создайте обработчик в потоке пользовательского интерфейса, а затем опубликуйте в нем Runable
Кирилл Кулаков
11
Еще раз: notifyDataSetChanged () не работает, по крайней мере, не для методов использования, которые рекомендуются (читать не рекомендуется). Если вы используете listview, адаптер курсора и контент-провайдера, вы можете попробовать что-то вроде: gettLoaderManager (). RestartLoader (). См .: stackoverflow.com/a/19657500/1087411 Я хотел бы увидеть хотя бы некоторую документацию по notifyDataSetChanged (). Чтоб в андроиде осталось тестирование черного ящика.
Андерсон
Если notifyDataSetChanged не работает, вы тот, кто делает это неправильно
zdarsky.peter
4
notifyDataSetChanged не всегда работает. Я не уверен, почему это в утверждении. Иногда вам нужно вызвать listView.setAdapter (адаптер), чтобы очистить старые представления. Смотрите также: stackoverflow.com/a/16261588/153275
1
Я так и не смог заставить работать notifyDataSetChanged. Я мог ясно видеть, что коллекция, которую я передаю адаптеру, изменилась (элементы были удалены), но notifyDataSetChanged никогда ничего не делал. Не уверен, что этот метод просто сломан?
Это правильный ответ, если нужно только перерисовать вид. Например, после входа пользователя в систему необходимо предоставить больше информации или параметров в каждом представлении listView. Это то, что мне нужно было сделать, поэтому проголосовал. Если базовые данные изменяются, возможно, лучше использовать notifyDataSetChanged ().
SBerg413
На самом деле invalidateViews()в наборах исходного кода, mDataChanged = true;поэтому я не уверен, что это приведет к лучшей производительности по сравнению сnotifyDataSetChanged()
vovahost
Ты спас мой день, чувак!
Оскарко
Вы можете взять тип списка, который является "наблюдаемым списком", нет необходимости изменять набор уведомлений
Priya
153
Пожалуйста , игнорировать все invalidate(), invalidateViews(), requestLayout(), ... ответы на этот вопрос.
Если вызов notifyDataSetChanged()не работает, все методы макета тоже не помогут. Поверьте мне, он ListViewбыл должным образом обновлен. Если вы не можете найти разницу, вам нужно проверить, откуда поступают данные в вашем адаптере.
Если это просто коллекция, которую вы храните в памяти, убедитесь, что вы действительно удалили или добавили элемент (ы) в коллекцию перед вызовом notifyDataSetChanged().
Если вы работаете с базой данных или бэкэндом службы, вам придется вызвать метод, чтобы снова получить информацию (или манипулировать данными в памяти) перед вызовом notifyDataSetChanged().
Дело в том, что это notifyDataSetChangedработает, только если набор данных изменился. Так что это место, чтобы посмотреть, если вы не обнаружите, что изменения происходят через. Отладка при необходимости.
ArrayAdapter против BaseAdapter
Я обнаружил, что работа с адаптером, который позволяет вам управлять коллекцией, например, BaseAdapter, работает лучше. Некоторые адаптеры, такие как ArrayAdapter, уже управляют собственной коллекцией, что затрудняет доступ к соответствующей коллекции для обновлений. Это действительно просто ненужный дополнительный уровень сложности в большинстве случаев.
Пользовательский интерфейс
Это правда, что это должно быть вызвано из потока пользовательского интерфейса. В других ответах есть примеры того, как этого добиться. Однако это требуется, только если вы работаете с этой информацией вне потока пользовательского интерфейса. Это из службы или потока не пользовательского интерфейса. В простых случаях вы будете обновлять свои данные с помощью нажатия кнопки или другого действия / фрагмента. Так что все еще в потоке пользовательского интерфейса. Нет необходимости всегда вставлять этот runOnUiTrhead в.
Быстрый пример проекта
Можно найти по адресу https://github.com/hanscappelle/so-2250770.git . Просто клонируйте и откройте проект в Android Studio (gradle). Этот проект имеет основной вид деятельностиListView со всеми случайными данными. Этот список можно обновить с помощью меню действий.
Реализация адаптера, которую я создал для этого примера ModelObject, предоставляет сбор данных.
publicclassMyListAdapterextendsBaseAdapter{/**
* this is our own collection of data, can be anything we
* want it to be as long as we get the abstract methods
* implemented using this data and work on this data
* (see getter) you should be fine
*/privateList<ModelObject> mData;/**
* our ctor for this adapter, we'll accept all the things
* we need here
*
* @param mData
*/publicMyListAdapter(finalContext context,finalList<ModelObject> mData){this.mData = mData;this.mContext = context;}publicList<ModelObject> getData(){return mData;}// implement all abstract methods here}
Код из MainActivity
publicclassMainActivityextendsActivity{privateMyListAdapter mAdapter;@Overrideprotectedvoid onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);ListView list =(ListView) findViewById(R.id.list);// create some dummy data hereList<ModelObject> objects = getRandomData();// and put it into an adapter for the list
mAdapter =newMyListAdapter(this, objects);
list.setAdapter(mAdapter);// mAdapter is available in the helper methods below and the // data will be updated based on action menu interactions// you could also keep the reference to the android ListView // object instead and use the {@link ListView#getAdapter()} // method instead. However you would have to cast that adapter // to your own instance every time}/**
* helper to show what happens when all data is new
*/privatevoid reloadAllData(){// get new modified random dataList<ModelObject> objects = getRandomData();// update data in our adapter
mAdapter.getData().clear();
mAdapter.getData().addAll(objects);// fire the event
mAdapter.notifyDataSetChanged();}/**
* helper to show how only changing properties of data
* elements also works
*/privatevoid scrambleChecked(){Random random =newRandom();// update data in our adapter, iterate all objects and // resetting the checked optionfor(ModelObject mo : mAdapter.getData()){
mo.setChecked(random.nextBoolean());}// fire the event
mAdapter.notifyDataSetChanged();}}
ты не прав. notifyDataSetChanged () не работал для меня, но invalidateViews () сделал это правильно.
Babay
6
У меня есть проблема, когда фактические элементы в списке не меняются, например, одинаковое количество элементов. Но проблема в том, что способ их представления должен измениться. Это означает, что код моего адаптера для создания пользовательского интерфейса должен быть запущен снова, а затем правильно скрыть некоторые элементы в строках списка. notifyDataSetChanged () не работает ...
Свен Хейгес
9
Этот ответ действительно помог мне. Я держал массив в памяти по определенным причинам. Чтобы это исправить я сейчас звоню adapter.clear(), а adapter.addAll(Array<T>)перед notifyDataSetChanged()
звонком
2
@hcpl, как мне вызвать notifyDataSetChanged, если я нахожусь в OnClickListener адаптера для CheckBox? invalidateViews выполняет свою работу прямо сейчас. Почему invalidateViews неправильный метод для вызова?
вытолкнул
1
Я так и не смог заставить работать notifyDataSetChanged. Я мог ясно видеть, что коллекция, которую я передаю адаптеру, изменилась (элементы были удалены), но notifyDataSetChanged никогда ничего не делал. Не уверен, что этот метод просто сломан?
до
42
Позвоните в любой момент, когда захотите:
runOnUiThread(run);
OnCreate()Вы устанавливаете свою работоспособную нить:
run =newRunnable(){publicvoid run(){//reload content
arraylist.clear();
arraylist.addAll(db.readAll());
adapter.notifyDataSetChanged();
listview.invalidateViews();
listview.refreshDrawableState();}};
Работает также в моем случае, когда мне нужно обновить просмотр списка на основе данных, поступающих из TCP-соединения (из потока «nonUI»). Единственный способ перерисовать список - очистить и заново добавить все элементы ArrayList. В любом случае, если вы уже находитесь в потоке пользовательского интерфейса, вам не нужно вызывать код через runOnUiThread()функцию.
Андре
Спасибо! Меня устраивает. Для всех людей, которые хотят запустить это из фрагмента, вы должны использовать getActivity (). RunOnUiThread (new Runnable ..., чтобы убедиться, что код запускается в потоке пользовательского интерфейса
codingpuss
Я не вижу цели run = new Runnable()и просто дал моей функции public void refreshUIThread()метод, который моделирует ваш run()метод (который тоже работает).
Т. Вуди,
11
у меня есть некоторые проблемы с динамическим обновлением моего списка.
Вызовите notifyDataSetChanged () на вашем адаптере.
Некоторые дополнительные подробности о том, как / когда вызывать notifyDataSetChanged (), можно посмотреть в этом видео Google I / O.
notifyDataSetChanged () не работал должным образом в моем случае [я вызвал notifyDataSetChanged из другого класса]. На всякий случай я отредактировал ListView в запущенном Activity (Thread). Это видео благодаря Кристоферу дало последний намек.
Во втором классе я использовал
Runnable run =newRunnable(){publicvoid run(){
contactsActivity.update();}};
contactsActivity.runOnUiThread(run);
чтобы получить доступ к обновлению () из моей деятельности. Это обновление включает в себя
myAdapter.notifyDataSetChanged();
чтобы сказать адаптеру обновить вид. Работал нормально, насколько я могу сказать.
если вы все еще не удовлетворены обновлением ListView, вы можете посмотреть на этот фрагмент, это для загрузки listView из БД. На самом деле, вам нужно просто перезагрузить ListView после выполнения любой операции CRUD. Это не лучший способ код, но он обновит ListView, как вы хотите ..
Это работает для меня .... если вы найдете лучшее решение, пожалуйста, поделитесь ...
.......
......
сделать ваши операции CRUD ..
......
.....
DBAdapter.open ();
DBAdapter.insert_into_SingleList ();
// Принесите этот DB_results и добавьте его в список как его содержимое ....
ls2.setAdapter (новый ArrayAdapter (DynTABSample.this,
android.R.layout.simple_list_item_1, DBAdapter.DB_ListView));
DBAdapter.close ();
Решения, предложенные людьми в этом посте, работают или нет в основном в зависимости от версии Android вашего устройства. Например, чтобы использовать метод AddAll, вы должны поместить android: minSdkVersion = "10" в ваше устройство Android.
Чтобы решить эти вопросы для всех устройств, я создал свой собственный метод в своем адаптере и использую внутри метода add и remove наследование от ArrayAdapter, который обновляет ваши данные без проблем.
Мой код: используя мой собственный класс данных RaceResult, вы используете свою собственную модель данных.
ResultGpRowAdapter.java
publicclassResultGpRowAdapterextendsArrayAdapter<RaceResult>{Context context;int resource;List<RaceResult> data=null;publicResultGpRowAdapter(Context context,int resource,List<RaceResult> objects){super(context, resource, objects);this.context = context;this.resource = resource;this.data = objects;}@OverridepublicView getView(int position,View convertView,ViewGroup parent){........}//my own method to populate data publicvoid myAddAll(List<RaceResult> items){for(RaceResult item:items){super.add(item);}}
ResultsGp.java
publicclassResultsGpextendsActivity{@Overrideprotectedvoid onCreate(Bundle savedInstanceState){......................ListView list =(ListView)findViewById(R.id.resultsGpList);ResultGpRowAdapter adapter =newResultGpRowAdapter(this, R.layout.activity_result_gp_row,newArrayList<RaceResult>());//Empty data
list.setAdapter(adapter);............//LOAD a ArrayList<RaceResult> with dataArrayList<RaceResult> data =newArrayList<RaceResult>();
data.add(newRaceResult(....));
data.add(newRaceResult(....));.......
adapter.myAddAll(data);//Your list will be udpdated!!!
Вам нужно использовать один объект из этого списка, который содержит данные, которые вы надуваете ListView. Если ссылка изменилась, значит, notifyDataSetChanged()она не работает. Когда вы удаляете элементы из списка, удалите их из списка, который вы используете, будь то ArrayList <> или что-то еще, затем Call
notifyDataSetChanged() on объект вашего класса адаптера.
Итак, посмотрите, как мне это удалось в моем адаптере, смотрите ниже.
Я не смог заставить notifyDataSetChanged () работать над обновлением моего SimpleAdapter, поэтому вместо этого я попытался сначала удалить все представления, которые были прикреплены к родительскому макету, с помощью removeAllViews (), затем добавить ListView, и это сработало, что позволило мне обновить UI:
Для меня после изменения информации в базе данных sql ничто не могло обновить представление списка (точнее, расширяемое представление списка), поэтому, если notifyDataSetChanged () не помогает, вы можете сначала попытаться очистить свой список и добавить его снова после этого вызова notifyDataSetChanged (). Например
Я был таким же, когда во фрагменте я хотел заполнить ListView (в одном TextView) с MAC-адресом устройств BLE, просканированных в течение некоторого времени.
Я думаю, это зависит от того, что вы подразумеваете под обновлением. Вы имеете в виду, что дисплей GUI должен быть обновлен, или вы имеете в виду, что дочерние представления должны быть обновлены так, чтобы вы могли программно вызвать getChildAt (int) и получить представление, соответствующее тому, что находится в адаптере.
Если вы хотите обновить отображение GUI, вызовите notifyDataSetChanged () на адаптере. Графический интерфейс будет обновлен при следующей перерисовке.
Если вы хотите иметь возможность вызывать getChildAt (int) и получать представление, которое отражает то, что находится в адаптере, то вызовите layoutChildren (). Это приведет к восстановлению дочернего представления по данным адаптера.
У меня был ArrayList, который я хотел отобразить в виде списка. ArrayList содержит элементы из mysql. Я переопределил метод onRefresh и в этом методе я использовал tablelayout.removeAllViews (); и затем повторил процесс для получения данных снова из базы данных. Но перед этим обязательно очистите ваш ArrayList или любую другую структуру данных, иначе новые данные будут добавлены к старому.
Если вы хотите обновить представление списка пользовательского интерфейса из службы, сделайте адаптер статичным в вашем основном действии и сделайте следующее:
Если вы идете по направляющим линиям Android и используете ContentProvidersданные для получения данных Databaseи отображаете их с ListViewпомощью кнопок CursorLoaderи CursorAdapters, то все изменения в связанных данных будут автоматически отражены в ListView.
При наведении getContext().getContentResolver().notifyChange(uri, null);курсора на ContentProviderбудет достаточно отразить изменения. Нет необходимости в дополнительной обработке.
Но когда вы не используете их все, вам нужно сообщить адаптеру, когда изменяется набор данных. Также вам нужно повторно заполнить / перезагрузить ваш набор данных (скажем, список), а затем вам нужно вызвать notifyDataSetChanged()адаптер.
notifyDataSetChanged()не будет работать, если нет изменений в наборе данных. Вот комментарий над методом в документации
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
Я смог получить notifyDataSetChanged, только получив новые данные адаптера, затем сбросив адаптер для представления списка, а затем сделав вызов следующим образом:
на другой вариант onWindowFocusChangedметод, но уверен, что он чувствителен и нуждается в некотором дополнительном кодировании для тех, кто заинтересован
override fun onWindowFocusChanged(hasFocus:Boolean){super.onWindowFocusChanged(hasFocus)// some controls needed
programList = usersDBHelper.readProgram(model.title!!)
notesAdapter =DailyAdapter(this, programList)
notesAdapter.notifyDataSetChanged()
listview_act_daily.adapter = notesAdapter
}
Если я говорил о моем сценарии здесь, ни один из приведенных выше ответов не будет работать, потому что у меня была активность, которая отображала список значений в БД вместе с кнопкой удаления, и когда была нажата кнопка удаления, я хотел удалить этот элемент из списка.
Круто было то, что я использовал не представление рециркулятора, а простое представление списка, и это представление списка инициализировалось в классе адаптера. Таким образом, вызов notifyDataSetChanged()метода не будет делать ничего внутри класса адаптера и даже в классе активности, где инициализируется объект адаптера, поскольку метод удаления был в классе адаптера.
Таким образом, решение состояло в том, чтобы удалить объект из адаптера в getViewметоде класса адаптера (чтобы удалить только этот конкретный объект, но если вы хотите удалить все, вызовитеclear() ).
Чтобы вы поняли, как выглядел мой код,
publicclassWordAdapterextendsArrayAdapter<Word>{Context context;publicWordAdapter(Activity context,ArrayList<Word> words){}//.......@NonNull@OverridepublicView getView(finalint position,View convertView,ViewGroupgroup){//.......ImageButton deleteBt = listItemView.findViewById(R.id.word_delete_bt);
deleteBt.setOnClickListener(newView.OnClickListener(){@Overridepublicvoid onClick(View v){if(vocabDb.deleteWord(currentWord.id)){//.....}else{//.....}remove(getItem(position));// <---- here is the trick ---<//clear() // if you want to clear everything}});//....
Примечание: здесь remove()и getItem()методы наследуются от класса Adapter.
remove() - удалить конкретный элемент, на который нажали
getItem(position) - получить элемент (здесь, это мой объект Word, который я добавил в список) из позиции, по которой щелкнули.
Вот как я установил адаптер на просмотр списка в классе активности,
Ответы:
Вызовите
notifyDataSetChanged()
свойAdapter
объект, как только вы изменили данные в этом адаптере.Некоторые дополнительные особенности о том , как / когда звонить
notifyDataSetChanged()
можно посмотреть в этом видео Google I / O .источник
Также вы можете использовать это:
источник
invalidateViews()
в наборах исходного кода,mDataChanged = true;
поэтому я не уверен, что это приведет к лучшей производительности по сравнению сnotifyDataSetChanged()
Пожалуйста , игнорировать все
invalidate()
,invalidateViews()
,requestLayout()
, ... ответы на этот вопрос.Правильно сделать (и, к счастью, также помечено как правильный ответ), это вызвать
notifyDataSetChanged()
свой адаптер .Поиск проблемы
Если вызов
notifyDataSetChanged()
не работает, все методы макета тоже не помогут. Поверьте мне, онListView
был должным образом обновлен. Если вы не можете найти разницу, вам нужно проверить, откуда поступают данные в вашем адаптере.Если это просто коллекция, которую вы храните в памяти, убедитесь, что вы действительно удалили или добавили элемент (ы) в коллекцию перед вызовом
notifyDataSetChanged()
.Если вы работаете с базой данных или бэкэндом службы, вам придется вызвать метод, чтобы снова получить информацию (или манипулировать данными в памяти) перед вызовом
notifyDataSetChanged()
.Дело в том, что это
notifyDataSetChanged
работает, только если набор данных изменился. Так что это место, чтобы посмотреть, если вы не обнаружите, что изменения происходят через. Отладка при необходимости.ArrayAdapter против BaseAdapter
Я обнаружил, что работа с адаптером, который позволяет вам управлять коллекцией, например, BaseAdapter, работает лучше. Некоторые адаптеры, такие как ArrayAdapter, уже управляют собственной коллекцией, что затрудняет доступ к соответствующей коллекции для обновлений. Это действительно просто ненужный дополнительный уровень сложности в большинстве случаев.
Пользовательский интерфейс
Это правда, что это должно быть вызвано из потока пользовательского интерфейса. В других ответах есть примеры того, как этого добиться. Однако это требуется, только если вы работаете с этой информацией вне потока пользовательского интерфейса. Это из службы или потока не пользовательского интерфейса. В простых случаях вы будете обновлять свои данные с помощью нажатия кнопки или другого действия / фрагмента. Так что все еще в потоке пользовательского интерфейса. Нет необходимости всегда вставлять этот runOnUiTrhead в.
Быстрый пример проекта
Можно найти по адресу https://github.com/hanscappelle/so-2250770.git . Просто клонируйте и откройте проект в Android Studio (gradle). Этот проект имеет основной вид деятельности
ListView
со всеми случайными данными. Этот список можно обновить с помощью меню действий.Реализация адаптера, которую я создал для этого примера ModelObject, предоставляет сбор данных.
Код из MainActivity
Больше информации
Еще один приятный пост о силе listViews находится здесь: http://www.vogella.com/articles/AndroidListView/article.html
источник
adapter.clear()
, аadapter.addAll(Array<T>)
передnotifyDataSetChanged()
Позвоните в любой момент, когда захотите:
OnCreate()
Вы устанавливаете свою работоспособную нить:источник
runOnUiThread()
функцию.run = new Runnable()
и просто дал моей функцииpublic void refreshUIThread()
метод, который моделирует вашrun()
метод (который тоже работает).у меня есть некоторые проблемы с динамическим обновлением моего списка.
notifyDataSetChanged () не работал должным образом в моем случае [я вызвал notifyDataSetChanged из другого класса]. На всякий случай я отредактировал ListView в запущенном Activity (Thread). Это видео благодаря Кристоферу дало последний намек.
Во втором классе я использовал
чтобы получить доступ к обновлению () из моей деятельности. Это обновление включает в себя
чтобы сказать адаптеру обновить вид. Работал нормально, насколько я могу сказать.
источник
Если вы используете SimpleCursorAdapter, попробуйте вызвать требуемый () для объекта Cursor.
источник
если вы все еще не удовлетворены обновлением ListView, вы можете посмотреть на этот фрагмент, это для загрузки listView из БД. На самом деле, вам нужно просто перезагрузить ListView после выполнения любой операции CRUD. Это не лучший способ код, но он обновит ListView, как вы хотите ..
Это работает для меня .... если вы найдете лучшее решение, пожалуйста, поделитесь ...
источник
Решения, предложенные людьми в этом посте, работают или нет в основном в зависимости от версии Android вашего устройства. Например, чтобы использовать метод AddAll, вы должны поместить android: minSdkVersion = "10" в ваше устройство Android.
Чтобы решить эти вопросы для всех устройств, я создал свой собственный метод в своем адаптере и использую внутри метода add и remove наследование от ArrayAdapter, который обновляет ваши данные без проблем.
Мой код: используя мой собственный класс данных RaceResult, вы используете свою собственную модель данных.
ResultGpRowAdapter.java
ResultsGp.java
источник
Если вы хотите сохранить свою позицию прокрутки при обновлении, и вы можете сделать это:
Для получения подробной информации, пожалуйста, смотрите Android ListView: Сохраняйте позицию прокрутки при обновлении .
источник
Просто используйте
myArrayList.remove(position);
внутри слушателя:источник
Вам нужно использовать один объект из этого списка, который содержит данные, которые вы надуваете
ListView
. Если ссылка изменилась, значит,notifyDataSetChanged()
она не работает. Когда вы удаляете элементы из списка, удалите их из списка, который вы используете, будь то ArrayList <> или что-то еще, затем CallnotifyDataSetChanged()
on объект вашего класса адаптера.Итак, посмотрите, как мне это удалось в моем адаптере, смотрите ниже.
источник
После удаления данных из списка, вам нужно позвонить
refreshDrawableState()
. Вот пример:и
deleteContact
метод вDatabaseHelper
классе будет выглядеть примерно такисточник
Я не смог заставить notifyDataSetChanged () работать над обновлением моего SimpleAdapter, поэтому вместо этого я попытался сначала удалить все представления, которые были прикреплены к родительскому макету, с помощью removeAllViews (), затем добавить ListView, и это сработало, что позволило мне обновить UI:
источник
Для меня после изменения информации в базе данных sql ничто не могло обновить представление списка (точнее, расширяемое представление списка), поэтому, если notifyDataSetChanged () не помогает, вы можете сначала попытаться очистить свой список и добавить его снова после этого вызова notifyDataSetChanged (). Например
Надеюсь, это имеет смысл для вас.
источник
при использовании SimpleCursorAdapter может вызывать changeCursor (newCursor) на адаптере.
источник
Я был таким же, когда во фрагменте я хотел заполнить ListView (в одном TextView) с MAC-адресом устройств BLE, просканированных в течение некоторого времени.
То, что я сделал, было это:
Затем ListView начал динамически заполняться MAC-адресами найденных устройств.
источник
Я думаю, это зависит от того, что вы подразумеваете под обновлением. Вы имеете в виду, что дисплей GUI должен быть обновлен, или вы имеете в виду, что дочерние представления должны быть обновлены так, чтобы вы могли программно вызвать getChildAt (int) и получить представление, соответствующее тому, что находится в адаптере.
Если вы хотите обновить отображение GUI, вызовите notifyDataSetChanged () на адаптере. Графический интерфейс будет обновлен при следующей перерисовке.
Если вы хотите иметь возможность вызывать getChildAt (int) и получать представление, которое отражает то, что находится в адаптере, то вызовите layoutChildren (). Это приведет к восстановлению дочернего представления по данным адаптера.
источник
У меня был ArrayList, который я хотел отобразить в виде списка. ArrayList содержит элементы из mysql. Я переопределил метод onRefresh и в этом методе я использовал tablelayout.removeAllViews (); и затем повторил процесс для получения данных снова из базы данных. Но перед этим обязательно очистите ваш ArrayList или любую другую структуру данных, иначе новые данные будут добавлены к старому.
источник
Если вы хотите обновить представление списка пользовательского интерфейса из службы, сделайте адаптер статичным в вашем основном действии и сделайте следующее:
источник
Если вы идете по направляющим линиям Android и используете
ContentProviders
данные для получения данныхDatabase
и отображаете их сListView
помощью кнопокCursorLoader
иCursorAdapters
, то все изменения в связанных данных будут автоматически отражены в ListView.При наведении
getContext().getContentResolver().notifyChange(uri, null);
курсора наContentProvider
будет достаточно отразить изменения. Нет необходимости в дополнительной обработке.Но когда вы не используете их все, вам нужно сообщить адаптеру, когда изменяется набор данных. Также вам нужно повторно заполнить / перезагрузить ваш набор данных (скажем, список), а затем вам нужно вызвать
notifyDataSetChanged()
адаптер.notifyDataSetChanged()
не будет работать, если нет изменений в наборе данных. Вот комментарий над методом в документацииисточник
Я смог получить notifyDataSetChanged, только получив новые данные адаптера, затем сбросив адаптер для представления списка, а затем сделав вызов следующим образом:
источник
на другой вариант
onWindowFocusChanged
метод, но уверен, что он чувствителен и нуждается в некотором дополнительном кодировании для тех, кто заинтересованисточник
Представьте, что вы передали список своему адаптеру.
Использование:
list.getAdapter().notifyDataSetChanged()
обновить свой список.
источник
Если я говорил о моем сценарии здесь, ни один из приведенных выше ответов не будет работать, потому что у меня была активность, которая отображала список значений в БД вместе с кнопкой удаления, и когда была нажата кнопка удаления, я хотел удалить этот элемент из списка.
Круто было то, что я использовал не представление рециркулятора, а простое представление списка, и это представление списка инициализировалось в классе адаптера. Таким образом, вызов
notifyDataSetChanged()
метода не будет делать ничего внутри класса адаптера и даже в классе активности, где инициализируется объект адаптера, поскольку метод удаления был в классе адаптера.Таким образом, решение состояло в том, чтобы удалить объект из адаптера в
getView
методе класса адаптера (чтобы удалить только этот конкретный объект, но если вы хотите удалить все, вызовитеclear()
).Чтобы вы поняли, как выглядел мой код,
Примечание: здесь
remove()
иgetItem()
методы наследуются от класса Adapter.remove()
- удалить конкретный элемент, на который нажалиgetItem(position)
- получить элемент (здесь, это мой объект Word, который я добавил в список) из позиции, по которой щелкнули.Вот как я установил адаптер на просмотр списка в классе активности,
источник
Проще всего сделать новый Adaper и уронить старый:
источник