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
arrayList
mientras 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 laarrayList
dearrayList
que 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();
}
});