example - spinner personalizado android studio
notifyDataSetChange no funciona desde un adaptador personalizado (7)
Cambia tu método de
public void updateReceiptsList(List<Receipt> newlist) {
receiptlist = newlist;
this.notifyDataSetChanged();
}
A
public void updateReceiptsList(List<Receipt> newlist) {
receiptlist.clear();
receiptlist.addAll(newlist);
this.notifyDataSetChanged();
}
Así que mantienes el mismo objeto que tu DataSet en tu Adaptador.
Cuando repobulo mi ListView , llamo a un método específico de mi Adapter .
Problema :
Cuando llamo updateReceiptsList desde mi Adapter , los datos se actualizan, pero mi ListView no refleja el cambio.
Pregunta :
¿Por qué mi ListView muestra los datos nuevos cuando llamo notifyDataSetChanged ?
Adaptador :
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;
}
}
--EDITAR:
solución encontrada
Solo para tener un código funcional que hago ahora:
listview.setAdapter( new ReceiptListAdapter(activity,mcontext, -new dataset-);
Funciona, pero no cómo se supone que funciona.
Como ya he explicado las razones detrás de este problema y también cómo manejarlo en un hilo de respuesta diferente Here . Todavía estoy compartiendo el resumen de la solución aquí.
Una de las razones principales por las que notifyDataSetChanged() no funcionará para usted, es decir,
Su adaptador pierde referencia a su lista .
Al crear y agregar una nueva lista al Adapter . Siempre siga estas pautas:
- Inicialice el
arrayListmientras lo declara globalmente. - Agregue la lista al adaptador directamente sin verificar los valores nulos y vacíos. Configure el adaptador directamente en la lista (no verifique ninguna condición). El adaptador le garantiza que siempre que realice cambios en los datos de la lista de
arrayList, se encargará de ello, pero nunca perderá la referencia. - Siempre modifique los datos en el arrayList mismo (si sus datos son completamente nuevos, puede llamar a
adapter.clear()yarrayList.clear()antes de agregar datos a la lista) pero no configure el adaptador, es decir, si los datos nuevos está poblado en laarrayListdearrayListque simplementeadapter.notifyDataSetChanged()
Espero que esto ayude.
Si el adapter está configurado en AutoCompleteTextView , notifyDataSetChanged() no funciona.
Necesito esto para actualizar el adaptador:
myAutoCompleteAdapter = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_dropdown_item_1line, myList);
myAutoComplete.setAdapter(myAutoCompleteAdapter);
Consulte: http://android-er.blogspot.in/2012/10/autocompletetextview-with-dynamic.html
Tal vez intente actualizar su ListView:
receiptsListView.invalidate() .
EDITAR: Otro pensamiento vino a mi mente. Solo para el registro, intente deshabilitar el caché de vista de lista:
<ListView
...
android:scrollingCache="false"
android:cacheColorHint="@android:color/transparent"
... />
Tengo el mismo problema, y me doy cuenta de eso. Cuando creamos el adaptador y lo establecemos en listview, listview apuntará al objeto en algún lugar de la memoria que el adaptador contendrá, los datos en este objeto se mostrarán en la vista de lista.
adapter = new CustomAdapter(data);
listview.setadapter(adapter);
si creamos un objeto para el adaptador con otra información de nuevo y notifydatasetchanged ():
adapter = new CustomAdapter(anotherdata);
adapter.notifyDataSetChanged();
esto no afectará a los datos en la vista de lista porque la lista apunta a un objeto diferente, este objeto no sabe nada sobre el nuevo objeto en el adaptador, y notifyDataSetChanged () no afecta a nada. Entonces deberíamos cambiar los datos en el objeto y evitar crear un nuevo objeto nuevamente para el adaptador
Tuve el mismo problema al utilizar ListAdapter
Dejé que Android Studio implementara métodos para mí y esto es lo que obtuve:
public class CustomAdapter implements ListAdapter {
...
@Override
public void registerDataSetObserver(DataSetObserver observer) {
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
...
}
El problema es que estos métodos no llaman super implementaciones, por lo que notifyDataSetChange nunca se llama.
Elimine estas anulaciones manualmente o agregue supercarrellas y debería funcionar de nuevo.
@Override
public void registerDataSetObserver(DataSetObserver observer) {
super.registerDataSetObserver(observer);
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
super.unregisterDataSetObserver(observer);
}
Agrega este código
runOnUiThread(new Runnable() { public void run() {
adapter = new CustomAdapter(anotherdata);
adapter.notifyDataSetChanged();
}
});