Android: notifyDataSetChanged(); не работает
У меня есть база данных на сервере и из Tablet. Я беру некоторые значения из одной таблицы в базе данных. Я правильно загружаю эту информацию в список, но я хотел бы знать, почему, когда происходит изменение, ничего не происходит, даже если я использую notifyDataSetChanged();
. Я должен сказать, что для загрузки данных загрузки y используйте AsyncTaskClass
Итак, моя проблема в том, что я не знаю, пользуетесь ли функцией notifyDataSetChanged(); метод правильно, потому что если есть изменение, я хотел бы обновить изображение. Вот некоторая часть кода класса:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.all_candidatos);
candidatosList = new ArrayList<HashMap<String, String>>();
new CargarCandidatos().execute();
}
// public void timer(){
// new CountDownTimer(tiempo, 100) {
//
// public void onTick(long millisUntilFinished) {
//
// }
//
// public void onFinish() {
// // new CargarCandidatos().execute();
//
// }
// }.start();}
/**
* Background Async Task to Load all product by making HTTP Request
* */
class CargarCandidatos extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(Monitorizacion.this);
pDialog.setMessage("Loading ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting All products from url
* */
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
JSONObject json = jParser.makeHttpRequest(url_candidatos, "GET", params);
Log.d("Candidatos: ", json.toString());
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
candidatos = json.getJSONArray(TAG_CANDIDATOS);
for (int i = 0; i < candidatos.length(); i++) {
JSONObject c = candidatos.getJSONObject(i);
// Storing each json item in variable
String nserie = c.getString(TAG_NSERIE);
String dni = c.getString(TAG_DNI);
String nombre = c.getString(TAG_NOMBRE);
String test = c.getString(TAG_TEST);
String pregunta = c.getString(TAG_PREGUNTA);
String bateria = c.getString(TAG_BATERIA);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_NSERIE, nserie);
map.put(TAG_DNI, dni);
map.put(TAG_NOMBRE, nombre);
map.put(TAG_TEST, test);
map.put(TAG_PREGUNTA, pregunta);
map.put(TAG_BATERIA, bateria);
// adding HashList to ArrayList
candidatosList.add(map);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
pDialog.dismiss();
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
adapter = new SimpleAdapter(
Monitorizacion.this, candidatosList,
R.layout.list_item, new String[] { TAG_NSERIE,
TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA},
new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria});
setListAdapter(adapter);
adapter.notifyDataSetChanged();
// timer();
}
});
}
}
}
Ответы
Ответ 1
Одна из основных причин notifyDataSetChanged()
не будет работать для вас - это,
Ваш адаптер потеряет ссылку на ваш список.
Когда вы сначала инициализируете Adapter
, он берет ссылку вашего arrayList
и передает ее своему суперклассу. Но если вы повторно инициализируете свой существующий arrayList
, он потеряет ссылку и, следовательно, канал связи с Adapter
.
При создании и добавлении нового списка в Adapter
. Всегда следуйте этим рекомендациям:
- Инициализируйте
arrayList
, объявив его глобально.
- Добавить список в адаптер напрямую без проверки на нуль и пустое
значения. Установите адаптер в список напрямую (не проверяйте
состояние). Адаптер гарантирует, что везде, где вы делаете
изменения данных
arrayList
он позаботится об этом, но никогда не потеряет
ссылка.
- Всегда изменяйте данные в самом массиве (если ваши данные совершенно новые
чем вы можете называть
adapter.clear()
и arrayList.clear()
до
фактически добавляя данные в список), но не устанавливайте адаптер i.e Если
новые данные заполняются в arrayList
, чем просто
adapter.notifyDataSetChanged()
Оставайтесь в курсе документации.
Ответ 2
Вещь, которую вы должны изменить, помещает ваш
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
adapter = new SimpleAdapter(
Monitorizacion.this, candidatosList,
R.layout.list_item, new String[] { TAG_NSERIE,
TAG_DNI, TAG_NOMBRE, TAG_TEST, TAG_PREGUNTA, TAG_BATERIA},
new int[] { R.id.id, R.id.dni, R.id.nombre, R.id.test, R.id.pregunta, R.id.bateria});
setListAdapter(adapter);
adapter.notifyDataSetChanged();
// timer();
}
});
в OnCreate(). и верните список candidatosList из Asynctask. чем установить таймер для обновления списка candidatosList.
Ответ 3
Возможно, стоит проверить, есть ли у вас пустое переопределение для registerDataSetObserver()
. Android Studio добавила один для меня, не выполняя вызов супер. Дополнить его следующим образом было достаточно, чтобы снова запустить мой ListView:
@Override
public void registerDataSetObserver(DataSetObserver observer) {
super.registerDataSetObserver(observer);
}
Ответ 4
Адаптер определяет компоновку макета!
- > setListAdapter(): определить адаптер для ListView/GridView/Gallery...
но вам нужно указать данные!
Я рекомендую вам инициализировать 'setListAdapter' в 'onCreate' или в конструкторе.
После установки данных в адаптер (пример: adapter.setItem(yourData))
И СЕЙЧАС! Вы должны позвонить notifyDataSetChanged!
Поскольку вы изменили данные, но представление не обновляется и notifydatasetchanged() перезагружает содержимое представления (ListView/GridView/Gallery...)
Для хорошей практики и понимания правильно я рекомендую вам использовать "пользовательский адаптер", используя " baseAdapter"
Прочитайте и сделайте это учебное пособие (я бы с этим учился): http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/
Прочтите документацию: http://developer.android.com/reference/android/widget/BaseAdapter.html
Ответ 5
Функция обновления должна вызываться из потока пользовательского интерфейса.
Мой ответ на самом деле похож на @user1621629 answer с той разницей, что я использую rxJava, поэтому здесь рабочий код, который решает эту проблему для меня:
this.subscriber = myAdapter.getSubscriber(); // keep for unsubscribe in destroy
dataSource.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread()).subscribe(this.subscriber);
Итак, я установил все выполнение, чтобы получить данные для списка в поток вычислений, но показывая результат в потоке пользовательского интерфейса.
Вот как я создаю для этого подписчика:
public class MyListAdapter extends RecyclerView.Adapter<LocationListAdapter.ViewHolder> {
private List<ListItem> mDataset = new ArrayList<>();
public Subscriber<ListItem[]> getSubscriber() {
return Subscribers.create(new Action1<ListItem[]>() {
@Override
public void call(ListItem[] listItems) {
mDataset.clear();
mDataset.addAll(Arrays.asList(listItems));
notifyDataSetChanged();
}
});
}
......
Ответ 6
Как Hissain описывает выше,
вам нужно сохранить ссылку на список
Вот как я получил его для работы:
-
Пусть список, отправленный в адаптер, будет установлен как член экземпляра в действии
-
В логике, которая выполняет изменение данных, убедитесь, что она обновляет тот же экземпляр списка, что и действие, переданное адаптеру
-
Затем вызов .notifyDataSetChanged(); работал
Помните, что позиция listView начинается с 1, поэтому вам нужно будет сделать (listViewPosition-1) для вашего java.util.List
Ответ 7
У меня нет большой репутации, чтобы комментировать ответ г-на Хисейна. Это правильно, но я хочу упомянуть еще об одном, что ссылка на список не должна меняться. Если базовый источник данных изменяется, не изменяйте ссылку на новый список. Действия должны выполняться только в том же объекте списка. Чтобы сделать то же самое, очистите список, используя clear(), а затем добавьте данные в тот же список, используя add() или addALL(), а затем вызовите notifyDataSetChanged(). например.
При первой инициализации списка
list = dataSource.getList();
то можно добавлять и удалять контент из списка и вызывать notifyDataSetChanged(), он работает нормально, но если в коде пытается изменить ссылку на другой объект. Как
list = dataSource.getList();
где getList() каждый раз возвращает новый список, поэтому ссылка на какой-либо другой объект списка и вызов notifyDataSetChnaged не влияет на список. Но если getList() возвращает один и тот же объект списка, он отлично работает.
Ответ 8
Если все, что вы установили нормально и все еще не работает, то ваш список...
Это Mutablekind из списка или нет...!
private val demoList: MutableList<AnyClass> = mutableListOf()
как только вы определили свой список, как указано выше, изменяемым образом, вы можете получить метод
.add
.addAll
.remove
и т.д....
иначе, если вы создали обычный список, это не будет работать как notifyDataSetChanged