Kiedy ponownie zapełniam mój ListView
, wywołuję określoną metodę z pliku my Adapter
.
Problem :
Kiedy dzwonię updateReceiptsList
z mojego Adapter
, dane są odświeżane, ale mój ListView
nie odzwierciedla zmiany.
Pytanie 30 :
Dlaczego nie ListView
pokazuję nowych danych, kiedy dzwonię notifyDataSetChanged
?
Adapter :
public class ReceiptListAdapter extends BaseAdapter {
public List<Receipt> receiptlist;
private Context context;
private LayoutInflater inflater;
private DateHelpers dateH;
public ReceiptListAdapter(Activity activity, Context mcontext, List<Receipt> rl) {
context = mcontext;
receiptlist = rl;
Collections.reverse(receiptlist);
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
dateH = new DateHelpers();
}
@Override
public int getCount() {
try {
int size = receiptlist.size();
return size;
} catch(NullPointerException ex) {
return 0;
}
}
public void updateReceiptsList(List<Receipt> newlist) {
receiptlist = newlist;
this.notifyDataSetChanged();
}
@Override
public Receipt getItem(int i) {
return receiptlist.get(i);
}
@Override
public long getItemId(int i) {
return receiptlist.get(i).getReceiptId() ;
}
private String getPuntenString(Receipt r) {
if(r.getPoints().equals("1")) {
return "1 punt";
}
return r.getPoints()+" punten";
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
final Receipt receipt = receiptlist.get(position);
ReceiptViewHolder receiptviewholder;
Typeface tf_hn = Typeface.createFromAsset(context.getAssets(), "helveticaneue.ttf");
Typeface tf_hn_bold = Typeface.createFromAsset(context.getAssets(), "helveticaneuebd.ttf");
if (vi == null) { //convertview==null
receiptviewholder = new ReceiptViewHolder();
vi = inflater.inflate(R.layout.view_listitem_receipt, null);
vi.setOnClickListener(null);
vi.setOnLongClickListener(null);
vi.setLongClickable(false);
receiptviewholder.shop = (TextView) vi.findViewById(R.id.tv_listitemreceipt_shop);
receiptviewholder.date = (TextView) vi.findViewById(R.id.tv_listitemreceipt_date);
receiptviewholder.price = (TextView) vi.findViewById(R.id.tv_listitemreceipt_price);
receiptviewholder.points = (TextView) vi.findViewById(R.id.tv_listitemreceipt_points);
receiptviewholder.shop.setTypeface(tf_hn_bold);
receiptviewholder.price.setTypeface(tf_hn_bold);
vi.setTag(receiptviewholder);
}else{//convertview is not null
receiptviewholder = (ReceiptViewHolder)vi.getTag();
}
receiptviewholder.shop.setText(receipt.getShop());
receiptviewholder.date.setText(dateH.timestampToDateString(Long.parseLong(receipt.getPurchaseDate())));
receiptviewholder.price.setText("€ "+receipt.getPrice());
receiptviewholder.points.setText(getPuntenString(receipt));
vi.setClickable(false);
return vi;
}
public static class ReceiptViewHolder {
public TextView shop;
public TextView date;
public TextView price;
public TextView points;
}
public Object getFilter() {
// XXX Auto-generated method stub
return null;
}
}
--EDYTOWAĆ:
znaleziono obejście
Żeby mieć jakiś funkcjonalny kod, robię teraz:
listview.setAdapter( new ReceiptListAdapter(activity,mcontext, -new dataset-);
Działa, ale nie tak, jak ma działać.
Odpowiedzi:
Zmień metodę z
Do
Więc zachowujesz ten sam obiekt co zestaw danych w adapterze.
źródło
ReceiptListObject
zamiastList
obiektów a, co możesz wtedy zrobić, aby rozwiązać ten problem?BaseAdapter
i ten adapter nie wie, z którymi danymi jest powiązany ... więc jeśli mam niestandardowy obiekt i używam niestandardowych funkcji tego obiektu (jakcustObject.getCount()
icustObject.getChildAt(int i)
na przykład), a chcę wymienić ten obiekt,notifyDataSetChanged
nie działa ... w każdym razie myślę, że ten problem nigdy nie występuje w przypadkuArrayAdapter
Mam ten sam problem i zdaję sobie z tego sprawę. Kiedy utworzymy adapter i ustawimy go na listview, listview wskaże obiekt gdzieś w pamięci, który zawiera adapter, dane w tym obiekcie będą wyświetlane w widoku listy.
jeśli ponownie utworzymy obiekt dla adaptera z innymi danymi i notifydatasetchanged ():
nie wpłynie to na dane w widoku listy, ponieważ lista wskazuje na inny obiekt, ten obiekt nie wie nic o nowym obiekcie w adapterze, a notifyDataSetChanged () nie wpływa na nic. Dlatego powinniśmy zmienić dane w obiekcie i unikać ponownego tworzenia nowego obiektu dla adaptera
źródło
Jak już wyjaśniłem przyczyny tego problemu, a także jak sobie z nim poradzić w innym wątku odpowiedzi tutaj . Wciąż udostępniam tutaj podsumowanie rozwiązania.
Jednym z głównych powodów
notifyDataSetChanged()
, dla których nie zadziała - jestTwoja karta traci odniesienie do listy .
Podczas tworzenia i dodawania nowej listy do
Adapter
. Zawsze przestrzegaj następujących wskazówek:arrayList
, deklarując to globalnie.arrayList
, zajmie się tym, ale nigdy nie zgubi referencji.adapter.clear()
iarrayList.clear()
przed faktycznym dodaniem danych do listy) ale nie ustawiaj adaptera, tj. Jeśli nowe dane są wypełnione warrayList
niż tylkoadapter.notifyDataSetChanged()
Mam nadzieję że to pomoże.
źródło
Może spróbuj odświeżyć ListView:
receiptsListView.invalidate()
.EDYCJA: Kolejna myśl przyszła mi do głowy. Dla przypomnienia, spróbuj wyłączyć pamięć podręczną widoku listy:
źródło
Miałem ten sam problem podczas używania
ListAdapter
Pozwoliłem Android Studio zaimplementować metody za mnie i oto co otrzymałem:
Problem polega na tym, że metody te nie wywołują
super
implementacji, więcnotifyDataSetChange
nigdy nie są wywoływane.Usuń te zastąpienia ręcznie lub dodaj super wywołania i powinno działać ponownie.
źródło
Możesz spróbować. To działa dla mnie
źródło
Jeśli
adapter
jest ustawiona naAutoCompleteTextView
tonotifyDataSetChanged()
, nie działa.Potrzebujesz tego do aktualizacji adaptera:
Zobacz: http://android-er.blogspot.in/2012/10/autocompletetextview-with-dynamic.html
źródło
Jeśli przypadkiem trafiłeś na ten wątek i zastanawiałeś się, dlaczego
adapter.invaidate()
lubadapter.clear()
metody nie są obecne w twoim przypadku, może dlatego, że możesz użyćRecyclerView.Adapter
zamiast tego,BaseAdapter
którego używa osoba zadająca to pytanie. Jeśli wyczyszczenielist
lubarraylist
nie rozwiązywanie problemu wtedy może się zdarzyć, że robisz dwa lub więcej wystąpień Spośródadapter
ex .:Główna aktywność
i
SomeFragment
Jeśli w drugim przypadku spodziewasz się zmiany na liście zawyżonych widoków w widoku recyklera, to się to nie stanie, ponieważ za drugim razem zostanie utworzona nowa instancja elementu,
adapter
która nie jest dołączona do widoku recyklera. UstawienienotifyDataSetChanged
w drugim adapterze nie zmieni zawartości widoku recyklera. W tym celu utwórz nową instancję widoku recyklera w SomeFragment i dołącz ją do nowej instancji adaptera.SomeFragment
Chociaż nie polecam tworzenia wielu instancji tego samego adaptera i widoku recyklera.
źródło
Dodaj ten kod
źródło
Mam ten sam problem, ale właśnie go skończyłem !!
powinieneś zmienić na
źródło
Mój przypadek był inny, ale może być tak samo dla innych
dla tych, którzy nadal nie mogli znaleźć rozwiązania i próbowali wszystkiego powyżej, jeśli używasz adaptera wewnątrz fragmentu, to powód, dla którego nie działa
fragment could be recreating so the adapter is recreating everytime the fragment recreate
przed zainicjowaniem należy sprawdzić, czy lista adapterów i obiektów ma wartość NULL
źródło