Обновление данных ArrayAdapter

Я создаю приложение, которое динамически заполняет/удаляет список массивов в зависимости от потока Futuretask, который взаимодействует с сервером.

Проблема в том, что когда я добавляю новый объект в свой адаптер массива и каким-либо образом вызываю notifyDataSetChanged или setNotifyOnChange

(например, после добавления элемента я также попытался создать некоторую функцию postadd, которая вызывает notifyDataSetChanged, или даже попытался добавить setNotifyOnChange в конструкторе адаптера или перед добавлением (adapter.setNotifyOnChange(true)))

в этой Futuretask он просто замораживает поток и вызывает сбои в работе приложения. Без уведомления об изменении, когда я провожу пальцем, чтобы вызвать метод getView() ArrayAdapter, он работает, но это нежелательное поведение.

Примечание. Я обращаюсь к адаптеру по ссылке на статическую переменную.

Примечание № 2: я не думаю, что создание нового адаптера снова и снова — разумный выбор.

/редактировать:

Мой метод удаления выглядит так:

public void remove (int itemid) {
        for (ContactItem i : items)
            if (i.ID == itemid)
                items.remove(i);
    }

(и зависает в итоге на последнем фарантесе)


person Smarty77    schedule 03.11.2014    source источник


Ответы (2)


  1. Передайте слабую ссылку на действие в другом потоке, чтобы избежать утечки контекста.

        WeakReference<Activity> mRef_Activity = new WeakReference<Activity>(activity);
    
  2. Из этого потока запустите уведомление об обновлении в потоке пользовательского интерфейса основного действия.

        final Activity activity = mRef_Activity.get();
        if(activity != null)
            activity.runOnUiThread(new Runnable() {
    
                @Override
                public void run() {
    
                    ArrayAdapter<String>  adapter = activity.getAdapter();
                    adapter.notifyDataSetChanged();
    
                }
            });
    

Обратите внимание, что если вы выполняете асинхронную задачу вместо вызываемой или выполняемой, вы можете просто поместить уведомление об обновлении в postExecute асинхронной задачи, так как это обратный вызов из основного потока пользовательского интерфейса.

person NameSpace    schedule 04.11.2014
comment
Здравствуйте, ваш ответ помог мне, спасибо, но я также испытываю очень странную ошибку. Я также добавил setNotifyOnChange(false); в конструктор адаптера, поэтому он не будет вызываться неявно, когда я пытаюсь добавить/удалить из списка, но все же иногда этот вызов происходит, когда я удаляю, и все приложение зависает, когда я нажимаю на экран, это то, что я получаю. - person Smarty77; 05.11.2014
comment
java.lang.IllegalStateException: содержимое адаптера изменилось, но ListView не получил уведомление. Убедитесь, что содержимое вашего адаптера не изменяется из фонового потока, а только из потока пользовательского интерфейса. Убедитесь, что ваш адаптер вызывает notifyDataSetChanged() при изменении его содержимого. [в ListView (2131427350, класс android.widget.ListView) с адаптером (класс censored.ui.adapters.ContactsAdapter)] - person Smarty77; 05.11.2014
comment
Документация для упомянутой вами функции. Если установлено значение false, вызывающая сторона должна вручную вызвать notifyDataSetChanged(), чтобы изменения отражались в прикрепленном представлении. Значение по умолчанию — true, и вызов notifyDataSetChanged() сбрасывает флаг в true. Кажется, вам нужно сбросить его после вызова notifyDataSetChanged(). - person NameSpace; 05.11.2014

  1. Использование ссылки на статическую переменную означает, что вы должны быть осторожны в потоке. Насколько я знаю, адаптер обновляет данные только в UI-потоке.
  2. Еще одна вещь, которую вы должны знать, это то, что вы должны реализовать функцию getCount() для возврата правильного числа. У меня была проблема, когда мой список не обновлял мои данные. даже я запускаю onDatasetChange(). Я забыл функцию getCount()
person kidnan1991    schedule 03.11.2014