Wenn ich meine ListView
wieder auffüllen, rufe ich eine bestimmte Methode von meiner Adapter
aus auf.
Problem :
Wenn ich updateReceiptsList
von meiner Adapter
aus anrufe, werden die Daten aktualisiert, aber meine ListView
gibt die Änderung nicht wieder.
Frage :
Warum zeigt meine ListView
die neuen Daten nicht an, wenn ich notifyDataSetChanged
anrufe?
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;
}
}
--BEARBEITEN:
gefundene Problemumgehung
Nur um etwas Funktionscode zu haben, den ich jetzt mache:
listview.setAdapter( new ReceiptListAdapter(activity,mcontext, -new dataset-);
Funktioniert, aber nicht so, wie es funktionieren soll.
Ändern Sie Ihre Methode von
public void updateReceiptsList(List<Receipt> newlist) {
receiptlist = newlist;
this.notifyDataSetChanged();
}
Zu
public void updateReceiptsList(List<Receipt> newlist) {
receiptlist.clear();
receiptlist.addAll(newlist);
this.notifyDataSetChanged();
}
Sie behalten also das gleiche Objekt wie Ihr DataSet in Ihrem Adapter.
Ich habe das gleiche Problem und das ist mir klar. Wenn wir einen Adapter erstellen und auf listview setzen, zeigt listview auf ein Objekt im Speicher des Adapters, und die Daten in diesem Objekt werden in der Listview angezeigt.
adapter = new CustomAdapter(data);
listview.setadapter(adapter);
wenn wir ein Objekt für den Adapter erneut mit anderen Daten erstellen und notifydatasetchanged ():
adapter = new CustomAdapter(anotherdata);
adapter.notifyDataSetChanged();
dies wirkt sich nicht auf Daten in der Listenansicht aus, da die Liste auf ein anderes Objekt verweist, dieses Objekt nichts über das neue Objekt im Adapter kennt und notifyDataSetChanged () nichts beeinflusst. Daher sollten wir die Daten im Objekt ändern und dies vermeiden Erstellen Sie erneut ein neues Objekt für den Adapter
Da ich bereits die Gründe für dieses Problem erklärt habe und auch, wie man es in einem anderen Antwort-Thread Here behandelt. Trotzdem teile ich die Lösungszusammenfassung hier.
Einer der Hauptgründe, warum notifyDataSetChanged()
für Sie nicht funktioniert - ist
Ihr Adapter verliert den Verweis auf Ihre Liste.
Beim Erstellen und Hinzufügen einer neuen Liste zu Adapter
. Befolgen Sie immer diese Richtlinien:
arrayList
, während Sie es global deklarieren.arrayList
vornehmen, sich dies darum kümmert, aber die Referenz niemals verloren geht.adapter.clear()
und arrayList.clear()
vor Tatsächlich Daten zur Liste hinzufügen), aber setzen Sie den Adapter nicht, dh If .__ Daten werden in arrayList
als nur adapter.notifyDataSetChanged()
aufgefüllt.Hoffe das hilft.
Versuchen Sie vielleicht, Ihre ListView zu aktualisieren:
receiptsListView.invalidate()
.
EDIT: Ein anderer Gedanke kam mir in den Sinn. Versuchen Sie für den Datensatz, den Listenansichts-Cache zu deaktivieren:
<ListView
...
Android:scrollingCache="false"
Android:cacheColorHint="@Android:color/transparent"
... />
Ich hatte das gleiche Problem mit ListAdapter
Ich lasse Android Studio Methoden für mich implementieren und das ist was ich habe:
public class CustomAdapter implements ListAdapter {
...
@Override
public void registerDataSetObserver(DataSetObserver observer) {
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
...
}
Das Problem ist, dass diese Methoden keine super
-Implementierungen aufrufen, sodass notifyDataSetChange
niemals aufgerufen wird.
Entfernen Sie diese Überschreibungen entweder manuell oder fügen Sie Superaufrufe hinzu, und es sollte wieder funktionieren.
@Override
public void registerDataSetObserver(DataSetObserver observer) {
super.registerDataSetObserver(observer);
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
super.unregisterDataSetObserver(observer);
}
Wenn adapter
auf AutoCompleteTextView
eingestellt ist, funktioniert notifyDataSetChanged()
nicht.
Benötigen Sie dies, um den Adapter zu aktualisieren:
myAutoCompleteAdapter = new ArrayAdapter<String>(MainActivity.this,
Android.R.layout.simple_dropdown_item_1line, myList);
myAutoComplete.setAdapter(myAutoCompleteAdapter);
Siehe: http://Android-er.blogspot.in/2012/10/autocompletetextview-with-dynamic.html
class StudentAdapter extends BaseAdapter {
ArrayList<LichHocDTO> studentList;
private void capNhatDuLieu(ArrayList<LichHocDTO> list){
this.studentList.clear();
this.studentList.addAll(list);
this.notifyDataSetChanged();
}
}
Du kannst es versuchen. Es funktioniert für mich
Diesen Code hinzufügen
runOnUiThread(new Runnable() { public void run() {
adapter = new CustomAdapter(anotherdata);
adapter.notifyDataSetChanged();
}
});
Ich habe das gleiche Problem, aber ich habe es gerade beendet !!
du solltest wechseln zu
public class ReceiptListAdapter erweitert BaseAdapter {
public List<Receipt> receiptlist;
private Context context;
private LayoutInflater inflater;
private DateHelpers dateH;
private List<ReceiptViewHolder> receiptviewlist;
public ReceiptListAdapter(Activity activity, Context mcontext, List<Receipt> rl) {
context = mcontext;
receiptlist = rl;
receiptviewlist = new ArrayList<>();
receiptviewlist.clear();
for(int i = 0; i < receiptlist.size(); i++){
ReceiptViewHolder receiptviewholder = new ReceiptViewHolder();
receiptviewlist.add(receiptviewholder);
}
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 receiptviewholder = receiptviewlist.get(position);
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;
}
}
Wenn Sie zufällig auf diesem Thread gelandet sind und sich fragen, warum adapter.invaidate()
oder adapter.clear()
Methoden in Ihrem Fall nicht vorhanden sind, dann vielleicht, weil Sie RecyclerView.Adapter
anstelle von BaseAdapter
verwenden wird vom Fragesteller dieser Frage verwendet. Wenn das Löschen von list
oder arraylist
Ihr Problem nicht behebt, kann es vorkommen, dass Sie zwei oder mehr Instanzen des adapter
ausführen, zum Beispiel:
Hauptaktivität
...
adapter = new CustomAdapter(list);
adapter.notifyDataSetChanged();
recyclerView.setAdapter(adapter);
...
und
SomeFragment
...
adapter = new CustomAdapter(newList);
adapter.notifyDataSetChanged();
...
Wenn Sie im zweiten Fall eine Änderung in der Liste der aufgeblasenen Ansichten in der Recycler-Ansicht erwarten, geschieht dies nicht, da beim zweiten Mal eine neue Instanz von adapter
erstellt wird, die nicht mit der Recycler-Ansicht verknüpft ist . Das Setzen von notifyDataSetChanged
im zweiten Adapter wird den Inhalt der Recycer-Ansicht nicht ändern. Erstellen Sie dazu eine neue Instanz der Recycler-Ansicht in SomeFragment und hängen Sie sie an die neue Instanz des Adapters an.
SomeFragment
...
recyclerView = new RecyclerView();
adapter = new CustomAdapter();
recyclerView.setAdapter(adapter);
...
Ich empfehle jedoch nicht, mehrere Instanzen derselben Adapter- und Recycler-Ansicht zu erstellen.