Domanda

Mio ListView sta usando un'estensione di BaseAdapter, Non riesco a farlo aggiornare correttamente. Quando mi aggiorno, sembra che i vecchi dati si disegnino sopra i nuovi dati, fino a quando non si verifica un evento di scorrimento. Le vecchie file si attingono sopra le nuove file, ma le vecchie file scompaiono quando inizio a scorrere.

Ho provato a chiamare invalidateViews(), notifyDataSetChanged(), e notifyDataSetInvalidated(). Il mio codice sembra qualcosa di simile:

private void updateData()
{
   List<DataItems> newList = getNewList();

   MyAdapter adapter = new MyAdapter(getContext());
   //my adapter holds an internal list of DataItems
   adapter.setList(newList);
   mList.setAdapter(adapter);
   adapter.notifyDataSetChanged();
   mList.invalidateViews();
}
È stato utile?

Soluzione

A chi ha ancora problemi, l'ho risolto in questo modo:

List<Item> newItems = databaseHandler.getItems();
ListArrayAdapter.clear();
ListArrayAdapter.addAll(newItems);
ListArrayAdapter.notifyDataSetChanged();
databaseHandler.close();

Ho prima cancellato i dati dall'adattatore, quindi ho aggiunto la nuova raccolta di articoli e solo poi imposta notifyDataSetChanged();All'inizio non era chiaro per me, quindi volevo sottolineare questo. Prendi nota che senza chiamare notifyDataSetChanged() La vista non sarà aggiornata.

Altri suggerimenti

A mia comprensione, se si desidera aggiornare immediatamente ListView quando i dati sono cambiati, dovresti chiamare notifyDataSetChanged() in RunOnUiThread().

private void updateData() {
    List<Data> newData = getYourNewData();
    mAdapter.setList(yourNewList);

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
                mAdapter.notifyDataSetChanged();
        }
    });
}

Non è necessario creare un nuovo adattatore per aggiornare il contenuto del tuo elenco. Basta archiviare l'adattatore in un campo e aggiornare l'elenco con il seguente codice:

mAdapter.setList(yourNewList);
mAdapter.notifyDataSetChanged();

Per chiarire questo, la tua attività dovrebbe apparire così:

private YourAdapter mAdapter;

protected void onCreate(...) {

    ...

    mAdapter = new YourAdapter(this);
    setListAdapter(mAdapter);

    updateData();
}

private void updateData() {
    List<Data> newData = getYourNewData();
    mAdapter.setList(yourNewList);
    mAdapter.notifyDataSetChanged();
}

Anch'io ho provato invalidate (), invalidateViews (), notifyDataSEtchanged (). Potrebbero funzionare tutti in alcuni contesti particolari, ma non ha fatto il lavoro nel mio caso.

Nel mio caso, ho dovuto aggiungere alcune nuove righe all'elenco e non funziona. La creazione di un nuovo adattatore ha risolto il problema.

Durante il debug, mi sono reso conto che i dati erano lì ma non sono stati resi. Se invalidate () o invalidateViews () non rendono (cosa che dovrebbe), non so cosa farebbe.

La creazione di un nuovo oggetto adattatore per aggiornare i dati modificati non sembra essere una cattiva idea. Funziona sicuramente. L'unico aspetto negativo potrebbe essere il tempo richiesto nell'allocazione di una nuova memoria per il tuo adattatore, ma ciò dovrebbe essere ok supponendo che il sistema Android sia abbastanza intelligente e si prende cura di ciò per mantenerlo efficiente.

Se lo togli dall'equazione, il flusso è quasi lo stesso di chiamare notifydatasetchanghed. Nel senso, in entrambi i casi viene chiamata la stessa serie di funzioni di adattatore.

Quindi non stiamo perdendo molto ma guadagniamo molto.

Penso che riempire lo stesso adattatore con dati diversi sarebbe una tecnica più o migliore. Inserisci questo metodo nella tua classe di adattatore con l'argomento giusto (l'elenco dei dati che si desidera visualizzare come nomi nel mio caso) chiamalo in cui aggiorna i dati dell'elenco con l'elenco aggiornato (nomi nel mio caso)

public void refill(ArrayList<BeanDatabase> names) {
    list.clear();
    list.addAll(names);
    list.notifyDataSetChanged();
}

Se si modifica l'adattatore o si imposta l'adattatore ancora e ancora quando l'elenco si aggiorna, forzare l'errore di chiusura causerebbe sicuramente problemi ad un certo punto. (Errore: i dati dell'elenco sono stati aggiornati ma l'adattatore non avvisa la visualizzazione dell'elenco)

Sto facendo la stessa cosa usando InvalidateViews () e questo funziona per me. Se vuoi che invalidisca immediatamente, potresti provare a chiamare PostInvalidate dopo aver chiamato InvalidateViews.

Aggiorna il contenuto di ListView di sotto il codice:

private ListView listViewBuddy;
private BuddyAdapter mBuddyAdapter;
private ArrayList<BuddyModel> buddyList = new ArrayList<BuddyModel>();

OnCreate ():

listViewBuddy = (ListView)findViewById(R.id.listViewBuddy);
mBuddyAdapter = new BuddyAdapter();
listViewBuddy.setAdapter(mBuddyAdapter);

ONDataget (Dopo WebService Call o da database locale o altro):

mBuddyAdapter.setData(buddyList);
mBuddyAdapter.notifyDataSetChanged();

Basadapter:

private class BuddyAdapter extends BaseAdapter { 

    private ArrayList<BuddyModel> mArrayList = new ArrayList<BuddyModel>();
    private LayoutInflater mLayoutInflater= (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    private ViewHolder holder;

    public void setData(ArrayList<BuddyModel> list){
        mArrayList = list;
    }

    @Override
    public int getCount() {
        return mArrayList.size();
    }

    @Override
    public BuddyModel getItem(int position) {
        return mArrayList.get(position);
    }

    @Override
    public long getItemId(int pos) {
        return pos;
    }

    private class ViewHolder {
        private TextView txtBuddyName, txtBuddyBadge;

    }
    @SuppressLint("InflateParams")
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = mLayoutInflater.inflate(R.layout.row_buddy, null);
            // bind views
            holder.txtBuddyName = (TextView) convertView.findViewById(R.id.txtBuddyName);
            holder.txtBuddyBadge = (TextView) convertView.findViewById(R.id.txtBuddyBadge);

            // set tag
            convertView.setTag(holder);
        } else {
            // get tag
            holder = (ViewHolder) convertView.getTag();
        }

        holder.txtBuddyName.setText(mArrayList.get(position).getFriendId());

        int badge = mArrayList.get(position).getCount();
        if(badge!=0){
            holder.txtBuddyBadge.setVisibility(View.VISIBLE);
            holder.txtBuddyBadge.setText(""+badge);
        }else{
            holder.txtBuddyBadge.setVisibility(View.GONE);
        }   

        return convertView;
    }
}

Ogni volta tu vuoi Aggiorna ListView Chiama Basta sotto il codice di due righe:

 mBuddyAdapter.setData(Your_Updated_ArrayList);
 mBuddyAdapter.notifyDataSetChanged();

Fatto

Solo questo funziona per me ogni volta, nota che non so se provoca altre complicazioni o problemi di prestazioni:

private void updateListView(){
        listview.setAdapter(adapter);
    }

Un altro modo semplice:

//In your ListViewActivity:
public void refreshListView() {
    listAdapter = new ListAdapter(this);
    setListAdapter(listAdapter);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top