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