PowiadomDataSetChanged przykład


166

Staram się używać w Android Applicationtej notifyDataSetChanged()metodzie dla ArrayAdapterale to nie działa dla mnie.

Znalazłem tutaj odpowiedź , która notifyDataSetChanged()powinna działać w głównym wątku, ale nie było na to przykładu.

Czy ktoś mógłby przesłać przykład lub przynajmniej link ?!



możesz sprawdzić tego bloga i ten przykład na githubie, a także to
Cabezas

Odpowiedzi:


328

W przypadku ArrayAdapter, notifyDataSetChangeddziała tylko w przypadku korzystania z add(), insert(), remove()i clear()na zasilaczu.

Kiedy ArrayAdapterjest konstruowany, przechowuje odniesienie do tego, Listco zostało przekazane. Jeśli miałbyś przekazać element, Listktóry był członkiem działania, i później zmienić ten element członkowski, ArrayAdapternadal zawiera odniesienie do oryginału List. Adapter nie wie, że zmieniłeśList działanie.

Masz do wyboru:

  1. Użyj funkcji ArrayAdaptermodyfikowania podstawowych list ( add(), insert(), remove(), clear(), itd.)
  2. Utwórz ponownie plik ArrayAdapterz nowymi Listdanymi. (Zużywa dużo zasobów i usuwa elementy bezużyteczne).
  3. Stwórz własną klasę pochodną od BaseAdapteri ListAdapterktóry pozwala na zmianę z podstawowej Liststruktury danych.
  4. Używaj za notifyDataSetChanged()każdym razem, gdy lista jest aktualizowana. Aby wywołać go w wątku interfejsu użytkownika, użyj runOnUiThread()of Activity. Wtedy notifyDataSetChanged()zadziała.

13
bądź też ostrożny z przypisywaniem „nowych” obiektów do swoich danych. zamiast tego użyj clear (), ponownie zapełnij / wprowadź zmiany w danych, a następnie wywołaj notifyDataSetChanged ()
moonlightcheese

Ale co, jeśli zadzwonimy notifyDataSetChanged()w ten sposób ((BaseAdapter) arrayAdapter).notifyDataSetChanged();:?
teoREtik

2
Używam BaseExpandableListAdapter, nie ma funkcji add () ani remove (), więc przechowuję moją mapę jako zmienną składową. Aktualizuję Mapę i wywołuję notifyDatasetChanged (), ale nic się nie dzieje. Kiedy używam opcji nr 4, działa. Czemu???
emeraldhieu

Używam ArrayAdapter dla niestandardowego widoku GridView, dodaję obrazy, gdy otrzymuję je z adresów URL, wywołując adapter.add (dataReceived). Działa to dobrze, dodaje dane, ale dlaczego jest odświeżane i przechodzi na górę. Chcę pokazać pozycje, ponieważ zostaną dodane bez odświeżania listy. (Co chcesz zrobić, to pracować z GridView systemu Android przy użyciu notifyDatasetChanged ()). Jak mogę to zrobić w tym niestandardowymGridView (StaggeredGridView).
MobileEvangelist

1
Próbowałem utworzyć własny BaseAdapter, aby dodać metody sortowania do listy, ale z jakiegoś powodu po prostu nie działało. Nie to, że moja aplikacja działa wolno, nawet jeśli odtworzę cały adapter z posortowaną listą arraylisty, ale nadal mnie to irytuje. Jak dokładnie stworzyłoby to dużo śmieci? Zakładam, że rzeczywista tablica kosztownych danych jest przechowywana jako odniesienie w działaniu wywołującym adapter, co oznacza, że ​​gromadzony będzie tylko adapter.
G_V

34

Możesz użyć tej runOnUiThread()metody w następujący sposób. Jeśli nie używasz ListActivity, po prostu dostosuj kod, aby uzyskać odniesienie do twojego ArrayAdapter.

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

1
Próbowałem dodać twój fragment kodu do mojego kodu (możesz go znaleźć tutaj stackoverflow.com/questions/3667442/how-to-refresh-adapter ) w onCreate-method, ale nadal nie mam żadnego sukcesu :( Może to było złe miejsce na dodanie go ?!
Tima,

1
Twoje pytanie dotyczyło właśnie sposobu wywołania metody i uruchomienia jej w głównym wątku interfejsu użytkownika. To odpowiada na to pytanie. W twoim konkretnym przypadku ( stackoverflow.com/questions/3670500/… ) AsyncTask i jego metoda onPostExecute () wydają się być tym, co powinieneś rozważyć.
Brian

12

Niedawno pisałem na ten temat, choć ten post był stary, pomyślałem, że przyda się komuś kto chce wiedzieć jak wdrożyć BaseAdapter.notifyDataSetChanged() krok po kroku i we właściwy sposób.

Postępuj zgodnie z instrukcjami Jak poprawnie zaimplementować BaseAdapter.notifyDataSetChanged () w systemie Android lub nowszym blogu BaseAdapter.notifyDataSetChanged () .


Cześć, wypróbowałem pierwszy przykład linku, ale zamiast mItem.add()tego zrobiłem po prostu edycję jednego elementu, co oznacza, że mItem.get(position).setImage(encodedImage)może to dlatego daje błąd z wyjątkiem NullPointer.Tak więc NotifyDataSetChange działa tylko na edycji, bcz dla karty Array, o której wspomniano powyżej, działa tylko dla add (), clear (), remove () etc
Shreekant N

notifyDataSetChanged będzie działać do edycji lub modyfikacji zestawu danych, twój pusty wskaźnik jest z czegoś innego, sprawdź dzienniki.
Arif Nadeem

7

Miałem ten sam problem i wolę nie zastępować w sposób ciągły całego ArrayAdapter nowym wystąpieniem. Dlatego mam AdapterHelper do podnoszenia ciężarów gdzie indziej.

Dodaj to w miejscu, w którym normalnie (próbowałbyś) wywołać powiadomienie

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

Klasa AdapterHelper

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

Mam kilka innych ArrayAdapters w moim kodzie i działały one bez problemu. Dziś wieczorem zdecydowałem się zamienić SimpleCursorAdapter na ArrayAdapter i NIE DZIAŁAŁO. Po kilku godzinach zmagań z nim i szukaniu przyczyny, dla której to nie działa, znalazłem twoją klasę AdapterHelper i TERAZ DZIAŁA! Dzięki!
dumgeekdad

1
Można to łatwo zrobić w funkcji ... DLACZEGO miałbyś utworzyć dla niej nową klasę?
techiServices

2
W Javie funkcje nazywane są metodami. Co byś zaproponował, być może ta metoda wielokrotnego użytku powinna znajdować się w tej samej klasie, co adapter macierzy? Lub fragment / działanie zawierające widok listy? Więc tak, jest w klasie, w której można go ponownie wykorzystać. Jeśli chcesz, aby wszystko było statyczne, śmiało.
Kevin Parker

1
Dobry pomysł. Innym rozwiązaniem byłoby rozszerzenie ArrayAdapter o nazwie ArrayAdapterCompat i zastąpienie metody addAll (..), ponieważ ta jest dostępna tylko od API 11. Tam sprawdź poziom API i użyj super.addAll(..)dla API> 11 i super.add (.. ) w połączeniu z iteracji jak twoja: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { super.addAll(items); } else { for (Object o : collection) { super.add(o); } }. Teraz po prostu rozszerz swoją nową klasę adaptera.
Konsumierer

Idealny! Wielkie dzięki @Kevin - to było DOKŁADNIE to, czego potrzebowałem!
Kibi,

3

Wiem, że to późna odpowiedź, ale miałem podobny problem i udało mi się go rozwiązać, używając notifyDataSetChanged()we właściwym miejscu.

Więc moja sytuacja wyglądała następująco.

Musiałem zaktualizować widok listy w zakładce paska akcji (fragment) z treścią zwróconą z zupełnie innej aktywności. Początkowo widok listy nie odzwierciedlałby jednak żadnych zmian. Jednak gdy kliknąłem inną kartę, a następnie wróciłem do żądanej karty, widok listy zostałby zaktualizowany o prawidłową treść z innej czynności. Aby rozwiązać ten problem, użyłem notifyDataSetChanged()adaptera paska akcji w kodzie działania, które miało zwrócić dane.

To jest fragment kodu, którego użyłem w ćwiczeniu.

@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).
    }
}

To działanie zwróciłoby niektóre dane do FragmentTab2i bezpośrednio zaktualizowałoby mój widok listy w FragmentTab2.

Mam nadzieję, że ktoś uzna to za przydatne!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.