Comment rafraîchir la vue de liste Android?


436

Comment rafraîchir un Android ListViewaprès avoir ajouté / supprimé des données dynamiques?


3
Si les autres solutions ne fonctionnent pas, essayez refreshDrawableState. Accessoires à stackoverflow.com/questions/5186359/…
Edwin Evans


Un exemple ici tutorialkart.com/kotlin-android/… peut vous aider.
Mallikarjun M

Réponses:


530

Appelez notifyDataSetChanged()votre Adapterobjet une fois que vous avez modifié les données de cet adaptateur.

En voici quelques détails supplémentaires sur la façon / quand appeler notifyDataSetChanged()peuvent être consultés dans cette vidéo Google I / O .


24
Vous devez l'exécuter sur le thread d'interface utilisateur. Créez un gestionnaire dans le thread d'interface utilisateur, puis postez-y Runable
Kirill Kulakov

11
Encore une fois: notifyDataSetChanged () ne fonctionne pas du moins pour les pratiques d'utilisation recommandées (lecture non déconseillée). Si vous utilisez listview, l'adaptateur de curseur et le fournisseur de contenu, vous pouvez essayer quelque chose du genre: gettLoaderManager (). RestartLoader (). Voir: stackoverflow.com/a/19657500/1087411 Je voudrais voir au moins de la documentation sur notifyDataSetChanged (). Trop dans Android est laissé aux tests de la boîte noire.
Anderson

Si notifyDataSetChanged ne fonctionne pas, c'est vous qui le faites mal
zdarsky.peter

4
notifyDataSetChanged ne fonctionne pas toujours. Je ne sais pas pourquoi cela est en litige. Parfois, vous devez appeler listView.setAdapter (adaptateur) pour effacer les anciennes vues. Voir aussi: stackoverflow.com/a/16261588/153275

1
Je n'ai jamais réussi à faire fonctionner notifyDataSetChanged. Je pouvais clairement voir que la collection que j'alimente à l'adaptateur a changé (les éléments ont été supprimés) mais notifyDataSetChanged n'a jamais rien fait. Vous ne savez pas si cette méthode est juste cassée?
byemute

204

Vous pouvez également utiliser ceci:

myListView.invalidateViews();

22
C'est la bonne réponse si l'on a seulement besoin de REDESSINER la vue. Par exemple, après la connexion d'un utilisateur, il doit afficher plus d'informations ou d'options dans chaque vue de listView. C'est ce que je devais faire, alors j'ai voté pour. Si les données sous-jacentes changent, c'est probablement une meilleure idée d'utiliser notifyDataSetChanged ().
SBerg413

En fait, invalidateViews()dans les ensembles de codes sources mDataChanged = true;, je ne sais pas si cela se traduit par de meilleures performances par rapport ànotifyDataSetChanged()
vovahost

Tu m'as sauvé la journée, mec!
oskarko

vous pouvez prendre un type de liste qui est "liste observable", pas besoin de notifydataset changé
Priya

153

S'il vous plaît ignorer tous les invalidate(), invalidateViews(), requestLayout(), ... réponses à cette question.

La bonne chose à faire (et heureusement également marquée comme bonne réponse) est de faire appel notifyDataSetChanged()à votre adaptateur .

Dépannage

Si l'appel notifyDataSetChanged()ne fonctionne pas, toutes les méthodes de mise en page ne seront pas utiles non plus. Croyez-moi, le a ListViewété correctement mis à jour. Si vous ne trouvez pas la différence, vous devez vérifier d'où proviennent les données de votre adaptateur.

S'il ne s'agit que d'une collection que vous gardez en mémoire, vérifiez que vous avez réellement supprimé ou ajouté les éléments à la collection avant d'appeler le notifyDataSetChanged().

Si vous travaillez avec une base de données ou un backend de service, vous devrez appeler la méthode pour récupérer à nouveau les informations (ou manipuler les données en mémoire) avant d'appeler le notifyDataSetChanged().

Le truc, c'est que cela notifyDataSetChangedne fonctionne que si l'ensemble de données a changé. C'est donc l'endroit à rechercher si vous ne trouvez pas de changements à venir. Déboguez si nécessaire.

ArrayAdapter vs BaseAdapter

J'ai trouvé que travailler avec un adaptateur qui vous permet de gérer la collection, comme un BaseAdapter fonctionne mieux. Certains adaptateurs comme ArrayAdapter gèrent déjà leur propre collection, ce qui rend plus difficile l'accès à la bonne collection pour les mises à jour. C'est vraiment juste une couche de difficulté supplémentaire inutile dans la plupart des cas.

Fil d'interface utilisateur

Il est vrai que cela doit être appelé à partir du thread d'interface utilisateur. D'autres réponses contiennent des exemples sur la façon d'y parvenir. Cependant, cela n'est requis que si vous travaillez sur ces informations en dehors du thread d'interface utilisateur. Cela provient d'un service ou d'un thread non UI. Dans des cas simples, vous mettrez à jour vos données à partir d'un clic sur un bouton ou d'une autre activité / fragment. Donc toujours dans le thread d'interface utilisateur. Pas besoin de toujours insérer ce runOnUiTrhead.

Exemple de projet rapide

Peut être trouvé à https://github.com/hanscappelle/so-2250770.git . Il vous suffit de cloner et d'ouvrir le projet dans Android Studio (gradle). Ce projet a un bâtiment MainAcitivityListView avec toutes les données aléatoires. Cette liste peut être actualisée à l'aide du menu d'action.

L'implémentation de l'adaptateur que j'ai créée pour cet exemple ModelObject expose la collecte de données

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
}

Code de la 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();
    }
}

Plus d'information

Un autre bon article sur la puissance de listViews se trouve ici: http://www.vogella.com/articles/AndroidListView/article.html


16
vous vous trompez. notifyDataSetChanged () n'a pas fonctionné pour moi, mais invalidateViews () l'a fait correctement.
babay

6
J'ai le problème où les éléments réels de la liste ne changent pas, par exemple la même quantité d'éléments. Mais le problème est que la façon dont ils sont présentés doit changer. Cela signifie que le code de mon adaptateur pour créer l'interface utilisateur doit s'exécuter à nouveau, puis masquer correctement certains éléments dans les lignes de la liste. notifyDataSetChanged () ne fonctionne pas ...
Sven Haiges

9
Cette réponse m'a vraiment aidé. Je gardais le tableau en mémoire pour certaines raisons de fonctionnalité. Pour résoudre ce problème adapter.clear(), j'appelle maintenant , et adapter.addAll(Array<T>)avant d'appelernotifyDataSetChanged()
Michael DePhillips

2
@hcpl, comment dois-je appeler notifyDataSetChanged si je suis dans OnClickListener de l'adaptateur pour un CheckBox? invalidateViews fait le travail en ce moment. Pourquoi invalidateViews n'est-il pas la bonne méthode à appeler?
grue le

1
Je n'ai jamais réussi à faire fonctionner notifyDataSetChanged. Je pouvais clairement voir que la collection que j'alimente à l'adaptateur a changé (les éléments ont été supprimés) mais notifyDataSetChanged n'a jamais rien fait. Vous ne savez pas si cette méthode est juste cassée?
byemute

42

Appelez runnable quand vous le souhaitez:

runOnUiThread(run);

OnCreate(), vous définissez votre thread exécutable:

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

1
Fonctionnant également dans mon cas, où j'ai besoin de mettre à jour une liste en fonction des données provenant d'une connexion TCP (à partir d'un thread "nonUI"). La seule façon de redessiner la liste était d'effacer et de rajouter tous les éléments de la ArrayList. Quoi qu'il en soit, si vous êtes déjà dans le thread d'interface utilisateur, vous n'avez pas besoin d'appeler le code via la runOnUiThread()fonction.
Andre

Merci! Ça marche pour moi. Pour toutes les personnes qui souhaitent exécuter cela à partir d'un fragment, vous devez utiliser getActivity (). RunOnUiThread (new Runnable ... pour vous assurer que le code est exécuté sur le thread d'interface utilisateur
codingpuss

Je ne vois pas le but de run = new Runnable()et ai juste donné à ma fonction une public void refreshUIThread()méthode qui modélise votre run()méthode (qui fonctionne aussi).
T.Woody

11

J'ai eu quelques problèmes avec l'actualisation dynamique de ma liste.

Appelez notifyDataSetChanged () sur votre adaptateur.

Quelques détails supplémentaires sur la façon / le moment d'appeler notifyDataSetChanged () peuvent être consultés dans cette vidéo Google I / O.

notifyDataSetChanged () ne fonctionnait pas correctement dans mon cas [j'ai appelé le notifyDataSetChanged d'une autre classe]. Juste au cas où j'ai édité le ListView dans l'activité en cours (Thread). Cette vidéo grâce à Christopher a donné l'ultime indice.

Dans ma deuxième classe, j'ai utilisé

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

pour accéder à la mise à jour () de mon Activité. Cette mise à jour comprend

myAdapter.notifyDataSetChanged();

pour indiquer à l'adaptateur d'actualiser la vue. A bien fonctionné pour autant que je puisse dire.



5

si vous n'êtes pas encore satisfait de l'actualisation de ListView, vous pouvez consulter cet extrait, c'est pour charger la listView à partir de la base de données.En réalité, ce que vous avez à faire est simplement de recharger ListView, après avoir effectué une opération CRUD, ce n'est pas le meilleur moyen de mais il actualisera le ListView comme vous le souhaitez.

Cela fonctionne pour moi .... si vous trouvez une meilleure solution, veuillez partager ...

.......
......
faites vos opérations CRUD ..
......
.....
DBAdapter.open ();
DBAdapter.insert_into_SingleList ();
// Apportez ces résultats DB et ajoutez-les à la liste en tant que contenu ....
                                            ls2.setAdapter (new ArrayAdapter (DynTABSample.this,
    android.R.layout.simple_list_item_1, DBAdapter.DB_ListView));
                                            DBAdapter.close ();

2

Les solutions proposées par les personnes dans ce post fonctionnent ou non en fonction principalement de la version Android de votre appareil. Par exemple, pour utiliser la méthode AddAll, vous devez mettre android: minSdkVersion = "10" dans votre appareil Android.

Pour résoudre ces questions pour tous les appareils, j'ai créé ma propre méthode dans mon adaptateur et j'utilise à l'intérieur de la méthode d'ajout et de suppression héritée d'ArrayAdapter qui met à jour vos données sans problème.

Mon code: en utilisant ma propre classe de données RaceResult, vous utilisez votre propre modèle de données.

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

Si vous souhaitez conserver votre position de défilement lorsque vous actualisez, et vous pouvez le faire:

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();
}

Pour les informations détaillées, veuillez consulter Android ListView: conservez votre position de défilement lorsque vous actualisez .


1

Utilisez simplement à l' myArrayList.remove(position);intérieur d'un écouteur:

  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

Vous devez utiliser un seul objet de cette liste dont les données que vous gonflez ListView . Si la référence est modifiée, notifyDataSetChanged()cela ne fonctionne pas. Chaque fois que vous supprimez des éléments de la liste, supprimez-les également de la liste que vous utilisez, qu'il s'agisse d'une liste de tableaux <> ou de quelque chose d'autre, puis appelez un notifyDataSetChanged()objet de votre classe d'adaptateur.

Alors, voici comment je l'ai géré dans mon adaptateur, voir ci-dessous

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
vos explications sont sous-estimées, mais cela me donne vraiment une compréhension de la référence arrayliste. merci
Abraham Putra Prakasa

0

Après avoir supprimé les données de la liste, vous devez appeler refreshDrawableState(). Voici l'exemple:

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

db.open();

db.deleteContact(arg3);

mListView.refreshDrawableState();

db.close();

et la deleteContactméthode en DatabaseHelperclasse ressemblera un peu

public boolean deleteContact(long rowId) {

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

}

0

Je n'ai pas pu obtenir notifyDataSetChanged () pour travailler sur la mise à jour de mon SimpleAdapter, j'ai donc essayé de supprimer d'abord toutes les vues qui étaient attachées à la disposition parent à l'aide de removeAllViews (), puis d'ajouter ListView, et cela a fonctionné, ce qui m'a permis de mettre à jour le 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

Pour moi, après avoir modifié les informations dans la base de données SQL, rien ne pouvait actualiser la vue de liste (pour être une vue de liste expansible spécifique), donc si notifyDataSetChanged () ne vous aide pas, vous pouvez essayer de vider votre liste en premier et de l'ajouter à nouveau après cet appel notifyDataSetChanged (). Par exemple

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

J'espère que cela a du sens pour vous.


0

lors de l'utilisation de SimpleCursorAdapter peut appeler changeCursor (newCursor) sur l'adaptateur.


0

J'étais le même lorsque, dans un fragment, j'ai voulu remplir un ListView (dans un seul TextView) avec l'adresse mac des appareils BLE scannés pendant un certain temps.

Ce que j'ai fait, c'est ceci:

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();
    }
}

Ensuite, le ListView a commencé à se remplir dynamiquement avec l'adresse mac des appareils trouvés.


0

Je pense que cela dépend de ce que vous entendez par rafraîchissement. Voulez-vous dire que l'affichage de l'interface graphique doit être actualisé, ou voulez-vous dire que les vues enfant doivent être actualisées de sorte que vous pouvez appeler par programme getChildAt (int) et obtenir la vue correspondant à ce qui se trouve dans l'adaptateur.

Si vous souhaitez que l'affichage de l'interface graphique soit actualisé, appelez notifyDataSetChanged () sur l'adaptateur. L'interface graphique sera actualisée lors du prochain redessin.

Si vous voulez pouvoir appeler getChildAt (int) et obtenir une vue qui reflète ce qui se trouve dans l'adaptateur, appelez alors layoutChildren (). Cela entraînera la reconstruction de la vue enfant à partir des données de l'adaptateur.


0

J'avais une ArrayList que je voulais afficher dans une liste. ArrayList contenait des éléments de mysql. J'ai remplacé la méthode onRefresh et dans cette méthode, j'ai utilisé tablelayout.removeAllViews (); puis répété le processus d'obtention à nouveau des données de la base de données. Mais avant cela, assurez-vous d'effacer votre ArrayList ou toute autre structure de données, sinon de nouvelles données seront ajoutées à l'ancienne.


0

Si vous souhaitez mettre à jour la liste de l'interface utilisateur à partir d'un service, rendez l'adaptateur statique dans votre activité principale et procédez comme suit:

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

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

0

Si vous utilisez des lignes de guidage Android et que vous utilisez ContentProviderspour obtenir des données Databaseet que vous les affichez à l' ListViewaide de CursorLoaderet CursorAdapters, alors toutes les modifications apportées aux données associées seront automatiquement reflétées dans ListView.

Votre getContext().getContentResolver().notifyChange(uri, null);curseur ContentProvidersera suffisant pour refléter les changements. Pas besoin de travail supplémentaire.

Mais lorsque vous ne les utilisez pas tous, vous devez indiquer à l'adaptateur lorsque l'ensemble de données change. Vous devez également repeupler / recharger votre jeu de données (par exemple, la liste), puis vous devez appeler notifyDataSetChanged()l'adaptateur.

notifyDataSetChanged()ne fonctionnera pas s'il n'y a pas de changements dans le jeu de données. Voici le commentaire au-dessus de la méthode dans docs-

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

0

Je n'ai pu obtenir notifyDataSetChanged qu'en obtenant de nouvelles données d'adaptateur, puis en réinitialisant l'adaptateur pour la vue de liste, puis en effectuant l'appel comme suit:

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

0

sur une autre option est la onWindowFocusChangedméthode, mais bien sûr, elle est sensible et a besoin d'un codage supplémentaire pour qui est intéressé

 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

Considérez que vous avez transmis une liste à votre adaptateur.
Utilisation:

list.getAdapter().notifyDataSetChanged()

pour mettre à jour votre liste.


0

Si j'ai parlé de mon scénario ici, aucune des réponses ci-dessus ne fonctionnera parce que j'ai eu une activité qui affiche la liste des valeurs de base de données avec un bouton de suppression et lorsqu'un bouton de suppression est enfoncé, je voulais supprimer cet élément de la liste.

Le truc cool, c'est que je n'ai pas utilisé la vue recycleur mais une simple vue liste et cette vue liste initialisée dans la classe adaptateur. Ainsi, l'appel à notifyDataSetChanged()ne fera rien à l'intérieur de la classe d'adaptateur et même dans la classe d'activité où l'objet adaptateur est initialisé car la méthode delete était dans la classe d'adaptateur.

Ainsi, la solution était de supprimer l'objet de l'adaptateur dans la getViewméthode de classe d'adaptateur (pour supprimer uniquement cet objet spécifique mais si vous souhaitez tout supprimer, appelez clear()).

Pour vous faire une idée, à quoi ressemblait mon code,

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
         }
    });
 //....

Remarque: ici remove()et les getItem()méthodes sont héritées de la classe Adapter.

  • remove() - pour supprimer l'élément spécifique qui est cliqué
  • getItem(position) - est d'obtenir l'élément (ici, c'est mon objet Word que j'ai ajouté à la liste) à partir de la position cliquée.

Voici comment j'ai défini l'adaptateur sur la liste dans la classe d'activité,

    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

Le plus simple est de simplement créer une nouvelle couche et de déposer l'ancienne:

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

Cela consomme plus de mémoire.
Player1

les ordures seront collectées
user1712200
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.