Come aggiornare la visualizzazione elenco Android?


Risposte:


530

Chiama notifyDataSetChanged()il tuo Adapteroggetto dopo aver modificato i dati in quell'adattatore.

Alcuni dettagli aggiuntivi su come / quando chiamare notifyDataSetChanged()possono essere visualizzati in questo video I / O di Google .


24
Dovresti eseguirlo sul thread dell'interfaccia utente. Crea un gestore all'interno del thread dell'interfaccia utente e poi pubblica Runable su di esso
Kirill Kulakov,

11
Ancora una volta: notifyDataSetChanged () non funziona almeno per le pratiche d'uso consigliate (leggi non deprecate). Se usi listview, l'adattatore del cursore e il provider di contenuti potresti provare qualcosa del genere: gettLoaderManager (). RestartLoader (). Vedi: stackoverflow.com/a/19657500/1087411 Vorrei vedere almeno un po 'di documentazione su notifyDataSetChanged (). Troppo in Android è lasciato ai test della scatola nera.
Anderson,

Se notifyDataSetChanged non funziona, sei tu quello che lo sta facendo di sbagliato
zdarsky.peter

4
notifyDataSetChanged non funziona sempre. Non sono sicuro del perché questo sia in conflitto. A volte è necessario chiamare listView.setAdapter (adattatore) per cancellare le vecchie visualizzazioni. Vedi anche: stackoverflow.com/a/16261588/153275

1
Non sono mai stato in grado di ottenere il funzionamento di NotifyDataSetChanged. Ho potuto vedere chiaramente che la raccolta che invio all'adattatore è cambiata (gli elementi sono stati rimossi) ma notifyDataSetChanged non ha mai fatto nulla. Non sei sicuro che questo metodo sia stato appena rotto?
Elimina il

204

Inoltre puoi usare questo:

myListView.invalidateViews();

22
Questa è la risposta corretta se si deve solo RIDURRE la vista. Ad esempio, dopo che si verifica un accesso utente che deve esporre più informazioni o opzioni all'interno di ciascuna vista di listView. Questo è quello che dovevo fare, quindi ho dato un voto positivo. Se i dati sottostanti cambiano, è probabilmente una migliore idea usare notifyDataSetChanged ().
SBerg413,

In realtà invalidateViews()nei set di codici sorgente, mDataChanged = true;quindi non sono sicuro che ciò si notifyDataSetChanged()
traduca

Mi hai salvato la giornata, amico!
Oskarko,

puoi prendere un tipo di elenco che è "elenco osservabile", non è necessario cambiare il set di notifiche
Priya

153

Si prega di ignorare tutto il invalidate(), invalidateViews(),requestLayout() , ... risposte a questa domanda.

La cosa giusta da fare (e fortunatamente anche contrassegnata come risposta giusta) è chiamare notifyDataSetChanged()il tuo adattatore .

Risoluzione dei problemi

Se la chiamata notifyDataSetChanged()non funziona, tutti i metodi di layout non saranno di aiuto. Credetemi, è ListViewstato correttamente aggiornato. Se non si riesce a trovare la differenza, è necessario verificare la provenienza dei dati nell'adattatore.

Se si tratta solo di una raccolta che stai tenendo in memoria, verifica di aver effettivamente eliminato o aggiunto gli elementi alla raccolta prima di chiamare il notifyDataSetChanged().

Se si lavora con un database o un back-end di servizio, è necessario chiamare il metodo per recuperare nuovamente le informazioni (o manipolare i dati in memoria) prima di chiamare il notifyDataSetChanged().

Il fatto è notifyDataSetChangedche funziona solo se il set di dati è cambiato. Questo è il posto dove cercare se non trovi cambiamenti in arrivo. Debug se necessario.

ArrayAdapter vs BaseAdapter

Ho scoperto che lavorare con un adattatore che ti consente di gestire la raccolta, come un BaseAdapter funziona meglio. Alcuni adattatori come ArrayAdapter gestiscono già la propria raccolta, rendendo più difficile accedere alla raccolta corretta per gli aggiornamenti. Nella maggior parte dei casi è davvero solo un inutile livello aggiuntivo di difficoltà.

Discussione UI

È vero che questo deve essere chiamato dal thread dell'interfaccia utente. Altre risposte hanno esempi su come raggiungere questo obiettivo. Tuttavia, questo è necessario solo se stai lavorando su queste informazioni al di fuori del thread dell'interfaccia utente. Questo proviene da un servizio o da un thread non UI. In casi semplici aggiornerai i tuoi dati da un clic sul pulsante o da un'altra attività / frammento. Quindi ancora all'interno del thread dell'interfaccia utente. Non è necessario inserire sempre quel runOnUiTrhead.

Esempio di progetto rapido

È disponibile all'indirizzo https://github.com/hanscappelle/so-2250770.git . Basta clonare e aprire il progetto in Android Studio (gradle). Questo progetto ha un edificio MainAcitivity aListView con tutti i dati casuali. Questo elenco può essere aggiornato utilizzando il menu azioni.

L'implementazione dell'adattatore che ho creato per questo esempio ModelObject espone la raccolta di dati

public class MyListAdapter extends BaseAdapter {

    /**
     * this is our own collection of data, can be anything we 
     * want it to be as long as we get the abstract methods 
     * implemented using this data and work on this data 
     * (see getter) you should be fine
     */
    private List<ModelObject> mData;

    /**
     * our ctor for this adapter, we'll accept all the things 
     * we need here
     *
     * @param mData
     */
    public MyListAdapter(final Context context, final List<ModelObject> mData) {
        this.mData = mData;
        this.mContext = context;
    }

    public List<ModelObject> getData() {
        return mData;
    }

    // implement all abstract methods here
}

Codice da MainActivity

public class MainActivity extends Activity {

    private MyListAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView list = (ListView) findViewById(R.id.list);

        // create some dummy data here
        List<ModelObject> objects = getRandomData();
        // and put it into an adapter for the list
        mAdapter = new MyListAdapter(this, objects);
        list.setAdapter(mAdapter);

        // mAdapter is available in the helper methods below and the 
        // data will be updated based on action menu interactions

        // you could also keep the reference to the android ListView 
        // object instead and use the {@link ListView#getAdapter()} 
        // method instead. However you would have to cast that adapter 
        // to your own instance every time
    }

    /**
     * helper to show what happens when all data is new
     */
    private void reloadAllData(){
        // get new modified random data
        List<ModelObject> objects = getRandomData();
        // update data in our adapter
        mAdapter.getData().clear();
        mAdapter.getData().addAll(objects);
        // fire the event
        mAdapter.notifyDataSetChanged();
    }

    /**
     * helper to show how only changing properties of data 
     * elements also works
     */
    private void scrambleChecked(){
        Random random = new Random();
        // update data in our adapter, iterate all objects and 
        // resetting the checked option
        for( ModelObject mo : mAdapter.getData()) {
            mo.setChecked(random.nextBoolean());
        }
        // fire the event
        mAdapter.notifyDataSetChanged();
    }
}

Maggiori informazioni

Un altro bel post sul potere di listViews è disponibile qui: http://www.vogella.com/articles/AndroidListView/article.html


16
hai torto. notifyDataSetChanged () non ha funzionato per me, ma invalidateViews () ha funzionato bene.
babay

6
Ho il problema per cui gli elementi effettivi nell'elenco non cambiano, ad esempio la stessa quantità di elementi. Ma il problema è che il modo in cui vengono presentati deve cambiare. Ciò significa che il codice del mio adattatore per creare l'interfaccia utente deve essere eseguito nuovamente e quindi nascondere correttamente alcuni elementi nelle righe dell'elenco. notifyDataSetChanged () non funziona ...
Sven Haiges

9
Questa risposta mi ha davvero aiutato. Stavo mantenendo l'array in memoria per alcuni motivi di funzionalità. Per risolvere il problema ora chiamo adapter.clear(), e adapter.addAll(Array<T>)prima di chiamarenotifyDataSetChanged()
Michael DePhillips,

2
@hcpl, come devo chiamare notificationDataSetChanged se mi trovo nella OnClickListener dell'adattatore per un CheckBox? invalidateViews sta eseguendo il lavoro in questo momento. Perché invalidateViews è il metodo sbagliato da chiamare?
Craned

1
Non sono mai stato in grado di ottenere il funzionamento di NotifyDataSetChanged. Ho potuto vedere chiaramente che la raccolta che invio all'adattatore è cambiata (gli elementi sono stati rimossi) ma notifyDataSetChanged non ha mai fatto nulla. Non sei sicuro che questo metodo sia stato appena rotto?
Elimina il

42

Chiama eseguibile quando vuoi:

runOnUiThread(run);

OnCreate(), hai impostato il tuo thread eseguibile:

run = new Runnable() {
    public void run() {
        //reload content
        arraylist.clear();
        arraylist.addAll(db.readAll());
        adapter.notifyDataSetChanged();
        listview.invalidateViews();
        listview.refreshDrawableState();
    }
};

1
Funzionando anche nel mio caso, in cui è necessario aggiornare una visualizzazione elenco basata sui dati provenienti da una connessione TCP (da un thread "nonUI"). L'unico modo per ridisegnare l'elenco era cancellare e aggiungere nuovamente tutti gli elementi di ArrayList. Ad ogni modo, se sei già nel thread dell'interfaccia utente, non è necessario chiamare il codice tramite la runOnUiThread()funzione.
Andre

Grazie! Per me funziona. Per tutte le persone che vogliono eseguirlo da un frammento, dovresti usare getActivity (). RunOnUiThread (nuovo Runnable ... per assicurarti che il codice sia eseguito sul thread dell'interfaccia utente
codingpuss

Non vedo lo scopo di run = new Runnable()e ho appena dato alla mia funzione un public void refreshUIThread()metodo che modella il tuo run()metodo (che funziona anche).
T.Woody,

11

ho avuto dei problemi con l'aggiornamento dinamico della mia lista.

Chiamare notifyDataSetChanged () sull'adattatore.

Alcuni dettagli aggiuntivi su come / quando chiamare notificationDataSetChanged () possono essere visualizzati in questo video I / O di Google.

notifyDataSetChanged () non ha funzionato correttamente nel mio caso [ho chiamato notifyDataSetChanged da un'altra classe]. Nel caso in cui ho modificato ListView nell'attività in esecuzione (Thread). Quel video grazie a Christopher ha dato il suggerimento finale.

Nella mia seconda classe ho usato

Runnable run = new Runnable(){
     public void run(){
         contactsActivity.update();
     }
};
contactsActivity.runOnUiThread(run);

per accedere all'aggiornamento () dalla mia attività. Questo aggiornamento include

myAdapter.notifyDataSetChanged();

per dire all'adattatore di aggiornare la vista. Ha funzionato bene per quanto posso dire.



5

se non sei ancora soddisfatto di ListView Refreshment, puoi guardare questo frammento, questo è per caricare listView da DB, In realtà quello che devi fare è semplicemente ricaricare ListView, dopo aver eseguito qualsiasi operazione CRUD Non è il modo migliore per codice, ma aggiornerà ListView come desideri.

Funziona per me .... se trovi una soluzione migliore, per favore Condividi ...

.......
......
fai le tue operazioni CRUD ..
......
.....
DBAdapter.open ();
DBAdapter.insert_into_SingleList ();
// Porta quel DB_results e aggiungilo alla lista come contenuto ....
                                            ls2.setAdapter (nuovo ArrayAdapter (DynTABSample.this,
    android.R.layout.simple_list_item_1, DBAdapter.DB_ListView));
                                            DBAdapter.close ();

2

Le soluzioni proposte dalle persone in questo post funzionano o non dipendono principalmente dalla versione Android del tuo dispositivo. Ad esempio, per utilizzare il metodo AddAll devi inserire android: minSdkVersion = "10" nel tuo dispositivo Android.

Per risolvere queste domande per tutti i dispositivi, ho creato il mio metodo personale nel mio adattatore e utilizzato all'interno del metodo di aggiunta e rimozione ereditato da ArrayAdapter che aggiorna i dati senza problemi.

Il mio codice: usando la mia classe di dati RaceResult, usi il tuo modello di dati.

ResultGpRowAdapter.java

public class ResultGpRowAdapter extends ArrayAdapter<RaceResult> {

    Context context;
    int resource;
    List<RaceResult> data=null;

        public ResultGpRowAdapter(Context context, int resource, List<RaceResult> objects)           {
        super(context, resource, objects);

        this.context = context;
        this.resource = resource;
        this.data = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ........
        }

        //my own method to populate data           
        public void myAddAll(List<RaceResult> items) {

        for (RaceResult item:items){
            super.add(item);
        }
    }

ResultsGp.java

public class ResultsGp extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {

    ...........
    ...........
    ListView list = (ListView)findViewById(R.id.resultsGpList); 

    ResultGpRowAdapter adapter = new ResultGpRowAdapter(this,  R.layout.activity_result_gp_row, new ArrayList<RaceResult>()); //Empty data

   list.setAdapter(adapter);

   .... 
   ....
   ....
   //LOAD a ArrayList<RaceResult> with data

   ArrayList<RaceResult> data = new ArrayList<RaceResult>();
   data.add(new RaceResult(....));
   data.add(new RaceResult(....));
   .......

   adapter.myAddAll(data); //Your list will be udpdated!!!

1

Se si desidera mantenere la posizione di scorrimento durante l'aggiornamento, è possibile effettuare questa operazione:

if (mEventListView.getAdapter() == null) {
    EventLogAdapter eventLogAdapter = new EventLogAdapter(mContext, events);
    mEventListView.setAdapter(eventLogAdapter);
} else {
    ((EventLogAdapter)mEventListView.getAdapter()).refill(events);
}

public void refill(List<EventLog> events) {
    mEvents.clear();
    mEvents.addAll(events);
    notifyDataSetChanged();
}

Per informazioni dettagliate, consultare Android ListView: mantenere la posizione di scorrimento durante l'aggiornamento .


1

Basta usare myArrayList.remove(position);all'interno di un ascoltatore:

  myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override public void onItemClick(AdapterView<?> parent, android.view.View view, int position, long id) {
           myArrayList.remove(position);
           myArrayAdapter.notifyDataSetChanged();
        }
    });

1

È necessario utilizzare un singolo oggetto dell'elenco per il quale si stanno gonfiando i dati ListView. Se il riferimento è una modifica, allora non notifyDataSetChanged()funziona. Ogni volta che si eliminano elementi dalla visualizzazione elenco, eliminarli anche dall'elenco che si sta utilizzando, sia ArrayList <> o Qualcos'altro, quindi Richiama notifyDataSetChanged()oggetto della classe dell'adattatore.

Quindi qui vedi come l'ho gestito nel mio adattatore vedi sotto

public class CountryCodeListAdapter extends BaseAdapter implements OnItemClickListener{

private Context context;
private ArrayList<CountryDataObject> dObj;
private ViewHolder holder;
private Typeface itemFont;
private int selectedPosition=-1;
private ArrayList<CountryDataObject> completeList;

public CountryCodeListAdapter(Context context, ArrayList<CountryDataObject> dObj) {
    this.context = context;
    this.dObj=dObj;
    completeList=new  ArrayList<CountryDataObject>();
    completeList.addAll(dObj);
    itemFont=Typeface.createFromAsset(context.getAssets(), "CaviarDreams.ttf");
}

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

@Override
public Object getItem(int position) {
    return dObj.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
    if(view==null){
        holder = new ViewHolder();
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.states_inflator_layout, null);
        holder.textView = ((TextView)view.findViewById(R.id.stateNameInflator));
        holder.checkImg=(ImageView)view.findViewById(R.id.checkBoxState);
        view.setTag(holder);
    }else{
        holder = (ViewHolder) view.getTag();
    }
    holder.textView.setText(dObj.get(position).getCountryName());
    holder.textView.setTypeface(itemFont);

    if(position==selectedPosition)
     {
         holder.checkImg.setImageResource(R.drawable.check);
     }
     else
     {
         holder.checkImg.setImageResource(R.drawable.uncheck);
     }
    return view;
}
private class ViewHolder{
    private TextView textView;
    private ImageView checkImg;
}

public void getFilter(String name) {
    dObj.clear();
    if(!name.equals("")){
    for (CountryDataObject item : completeList) {
        if(item.getCountryName().toLowerCase().startsWith(name.toLowerCase(),0)){
            dObj.add(item);
        }
    }
    }
    else {
        dObj.addAll(completeList);
    }
    selectedPosition=-1;
    notifyDataSetChanged();
    notifyDataSetInvalidated(); 
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
        long id) {
    Registration reg=(Registration)context;
    selectedPosition=position;
    reg.setSelectedCountryCode("+"+dObj.get(position).getCountryCode());
    notifyDataSetChanged();
}
}

1
la tua spiegazione è sottovalutata, ma mi dà davvero comprensione sul riferimento dell'arraylist. grazie
Abraham Putra Prakasa,

0

Dopo aver eliminato i dati dalla visualizzazione elenco, è necessario chiamare refreshDrawableState(). Ecco l'esempio:

final DatabaseHelper db = new DatabaseHelper (ActivityName.this);

db.open();

db.deleteContact(arg3);

mListView.refreshDrawableState();

db.close();

e il deleteContactmetodo in DatabaseHelperclasse sarà in qualche modo simile

public boolean deleteContact(long rowId) {

   return db.delete(TABLE_NAME, BaseColumns._ID + "=" + rowId, null) > 0;

}

0

Non sono stato in grado di fare in modo che notificationDataSetChanged () funzionasse sull'aggiornamento del mio SimpleAdapter, quindi ho provato prima a rimuovere tutte le viste associate al layout principale usando removeAllViews (), quindi aggiungendo ListView e che ha funzionato, permettendomi di aggiornare il UI:

LinearLayout results = (LinearLayout)findViewById(R.id.results);
ListView lv = new ListView(this);
ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
SimpleAdapter adapter = new SimpleAdapter( this, list, R.layout.directory_row, 
                new String[] { "name", "dept" }, new int[] { R.id.name, R.id.dept } );

for (...) { 
    HashMap<String, String> map = new HashMap<String, String>();
    map.put("name", name);
    map.put("dept", dept);
    list.add(map);
}

lv.setAdapter(adapter);
results.removeAllViews();     
results.addView(lv);

0

Per me, dopo aver modificato le informazioni nel database sql, nulla potrebbe aggiornare la visualizzazione elenco (per essere specifica visualizzazione elenco espandibile), quindi se notificationDataSetChanged () non aiuta, puoi provare a cancellare prima il tuo elenco e aggiungerlo di nuovo dopo quella chiamata notificationDataSetChanged (). Per esempio

private List<List<SomeNewArray>> arrayList;
List<SomeNewArray> array1= getArrayList(...);
List<SomeNewArray> array2= getArrayList(...);
arrayList.clear();
arrayList.add(array1);
arrayList.add(array2);
notifyDataSetChanged();

Spero abbia senso per te.


0

durante l'utilizzo di SimpleCursorAdapter è possibile chiamare changeCursor (newCursor) sull'adattatore.


0

Ero lo stesso quando, in un frammento, volevo popolare un ListView (in un singolo TextView) con l'indirizzo mac dei dispositivi BLE scansionati nel tempo.

Quello che ho fatto è stato questo:

public class Fragment01 extends android.support.v4.app.Fragment implements ...
{
    private ListView                listView;
    private ArrayAdapter<String>    arrayAdapter_string;

...

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    ...
    this.listView= (ListView) super.getActivity().findViewById(R.id.fragment01_listView);
    ...
    this.arrayAdapter_string= new ArrayAdapter<String>(super.getActivity(), R.layout.dispositivo_ble_item, R.id.fragment01_item_textView_titulo);
    this.listView.setAdapter(this.arrayAdapter_string);
}


@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
{
    ...
    super.getActivity().runOnUiThread(new RefreshListView(device));
}


private class RefreshListView implements Runnable
{
    private BluetoothDevice bluetoothDevice;

    public RefreshListView(BluetoothDevice bluetoothDevice)
    {
        this.bluetoothDevice= bluetoothDevice;
    }

    @Override
    public void run()
    {
        Fragment01.this.arrayAdapter_string.add(new String(bluetoothDevice.toString()));
        Fragment01.this.arrayAdapter_string.notifyDataSetChanged();
    }
}

Quindi ListView ha iniziato a popolare dinamicamente con l'indirizzo mac dei dispositivi trovati.


0

Penso che dipenda da cosa intendi per aggiornamento. Vuoi dire che la visualizzazione della GUI dovrebbe essere aggiornata, o vuoi dire che le viste figlio dovrebbero essere aggiornate in modo tale da poter chiamare programmaticamente getChildAt (int) e ottenere la vista corrispondente a ciò che è nell'adapter.

Se si desidera aggiornare la visualizzazione della GUI, quindi chiamare notifyDataSetChanged () sull'adattatore. La GUI verrà aggiornata al prossimo ridisegno.

Se vuoi essere in grado di chiamare getChildAt (int) e ottenere una vista che riflette ciò che è ciò che è nell'adattatore, quindi chiama a layoutChildren (). Ciò causerà la ricostruzione della vista figlio dai dati dell'adattatore.


0

Avevo un ArrayList che volevo visualizzare in una lista. ArrayList conteneva elementi da mysql. Ho ignorato il metodo onRefresh e in quel metodo ho usato tablelayout.removeAllViews (); e quindi ha ripetuto il processo per ottenere nuovamente i dati dal database. Ma prima assicurati di cancellare la tua ArrayList o qualunque altra struttura di dati o nuovi dati verranno aggiunti a quello vecchio ..


0

Se si desidera aggiornare la visualizzazione elenco UI da un servizio, quindi rendere l'adattatore statico nella propria attività principale e procedere come segue:

@Override
public void onDestroy() {
    if (MainActivity.isInFront == true) {
        if (MainActivity.adapter != null) {
            MainActivity.adapter.notifyDataSetChanged();
        }

        MainActivity.listView.setAdapter(MainActivity.adapter);
    }
}    

0

Se stai seguendo le linee guida Android e stai utilizzando il ContentProvidersper ottenere i dati da Databasee li stai visualizzando ListViewnell'uso del CursorLoadere CursorAdapters, quindi tutte le modifiche ai dati correlati verranno automaticamente riflesse in ListView.

Il getContext().getContentResolver().notifyChange(uri, null);cursore del mouse su ContentProvidersarà sufficiente per riflettere le modifiche. Non è necessario alcun lavoro aggiuntivo.

Ma quando non li usi tutti, devi dire all'adattatore quando il set di dati sta cambiando. Inoltre, è necessario popolare nuovamente / ricaricare il set di dati (ad esempio l'elenco) e quindi è necessario chiamare notifyDataSetChanged()l'adattatore.

notifyDataSetChanged()non funzionerà se non ci sono cambiamenti nel datset. Ecco il commento sopra il metodo in docs-

/**
 * Notifies the attached observers that the underlying data has been changed
 * and any View reflecting the data set should refresh itself.
 */

0

Sono stato in grado di ottenere notificationDataSetChanged solo ottenendo nuovi dati dell'adattatore, quindi ripristinando l'adattatore per la visualizzazione elenco, quindi effettuando la chiamata in questo modo:

    expandableAdapter = baseFragmentParent.setupEXLVAdapter();
    baseFragmentParent.setAdapter(expandableAdapter);
    expandableAdapter.notifyDataSetChanged(); 

0

su un'altra opzione è il onWindowFocusChangedmetodo, ma sicuramente è sensibile e necessita di qualche codice aggiuntivo per chi è interessato

 override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)

       // some controls needed
        programList = usersDBHelper.readProgram(model.title!!)
        notesAdapter = DailyAdapter(this, programList)
        notesAdapter.notifyDataSetChanged()
        listview_act_daily.adapter = notesAdapter
    }

0

Considera di aver passato un elenco al tuo adattatore.
Uso:

list.getAdapter().notifyDataSetChanged()

per aggiornare il tuo elenco.


0

Se ho parlato del mio scenario qui, le risposte non precedenti non funzioneranno perché avevo un'attività che mostrava un elenco di valori db insieme a un pulsante Elimina e quando si preme un pulsante Elimina, volevo eliminare quell'elemento dall'elenco.

La cosa interessante è che non ho usato la vista Riciclatore ma una semplice vista elenco e quella vista elenco inizializzata nella classe dell'adattatore. Quindi, chiamare il notifyDataSetChanged()non farà nulla all'interno della classe dell'adattatore e nemmeno nella classe di attività in cui l'oggetto adattatore è inizializzato perché il metodo di eliminazione era nella classe dell'adattatore.

Quindi, la soluzione era rimuovere l'oggetto dall'adattatore nel getViewmetodo della classe dell'adattatore (per eliminare solo quell'oggetto specifico ma se si desidera eliminare tutto, chiamare clear()).

A te per avere un'idea di come fosse il mio codice,

public class WordAdapter extends ArrayAdapter<Word> {
  Context context;

  public WordAdapter(Activity context, ArrayList<Word> words) {}
    //.......

    @NonNull
    @Override
    public View getView(final int position, View convertView, ViewGroup group) {
      //.......
     ImageButton deleteBt = listItemView.findViewById(R.id.word_delete_bt);
     deleteBt.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             if (vocabDb.deleteWord(currentWord.id)) {
                //.....
             } else{
                //.....
             }
             remove(getItem(position)); // <---- here is the trick ---<
             //clear() // if you want to clear everything
         }
    });
 //....

Nota: qui remove()e i getItem()metodi sono ereditati dalla classe Adapter.

  • remove() - per rimuovere l'elemento specifico su cui si fa clic
  • getItem(position) - è quello di ottenere l'elemento (qui, questo è il mio oggetto Word che ho aggiunto all'elenco) dalla posizione cliccata.

Ecco come ho impostato l'adattatore per la visualizzazione elenco nella classe di attività,

    ArrayList<Word> wordList = new ArrayList();
    WordAdapter adapter = new WordAdapter(this, wordList);

    ListView list_view = (ListView) findViewById(R.id.activity_view_words);
    list_view.setAdapter(adapter);

-1

Il più semplice è semplicemente creare un nuovo Adaper e rilasciare quello vecchio:

myListView.setAdapter(new MyListAdapter(...));

Questo consuma più memoria.
Giocatore1,

la spazzatura sarà raccolta
user1712200,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.