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.