web-dev-qa-db-fra.com

notifyDataSetChanged () actualise la liste et fait défiler vers le haut

J'essaie d'implémenter une liste de défilement sans fin, mais lorsque j'appelle notifyDataSetChanged(), la liste entière est actualisée, puis la position de défilement revient au début.

Est-ce le comportement normal? comment puis-je simplement faire ajouter les éléments ajoutés sans rafraîchir et garder la position de défilement?

25
code511788465541441

Un tel comportement n'est pas normal. Sans voir votre code, je peux suggérer de suivre:

1) Vous n'appelez pas notifyDataSetChanged() à partir du thread d'interface utilisateur. La bonne manière:

runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }
});

2) Vous appelez accidentellement ou non à adapter.notifyDataSetInvalidated();

3) Dans votre adaptateur, vous substituez la méthode adapter.notifyDataSetChanged(); et ajoutez des instructions pour atteindre le sommet. 

4) Si vous utilisez une liste pour renseigner un adaptateur, vous fournissez une nouvelle liste à chaque fois. Les paramètres de l’adaptateur sont donc actualisés. Vous devriez toujours fournir la même liste. Cependant, vous pouvez le changer autant que vous le souhaitez. Si vous réinitialisez la liste, utilisez list.clear au lieu de list = new ArrayList();

Voici un exemple de mon adaptateur:

public class Adapter extends BaseAdapter {

    private Activity activity;
    private ArrayList<HashMap<String, String>> data;
    private static LayoutInflater inflater = null;
    public ImageLoader imageLoader;

    public MediaItemAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
        activity = a;
        data = d;
        inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader = new ImageLoader(activity.getApplicationContext());
    }

    public int getCount() {
        return data.size();
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi = convertView;
        if (convertView == null) {
            vi = inflater.inflate(R.layout.item_composer, null);
        }
        TextView title = (TextView) vi.findViewById(R.id.item_title); // title
        TextView price = (TextView) vi.findViewById(R.id.price);


        return vi;
    }


}

Appelez pour un adaptateur:

List myList = new ArrayList<HashMap<String, String>>();
Adapter ma = new Adapter(this, myList);

myList peut être vide avant l'initialisation de l'adaptateur.

Puis faites quelques opérations avec ma liste:

myList.add(someElement);
ma.notifyDataSetChanged();

si vous avez besoin de supprimer tous les éléments:

myList.clear();
ma.notifyDataSetChanged();

Une telle implémentation est sans fin, j'ai vu plus de 15 mille éléments sans aucun problème.

61
Yarh

Dans mon cas, le problème était que j'appelais ListView.setAdapter(adapter) chaque fois que de nouvelles données étaient définies, ce qui réinitialisait également la position et la vue passait au sommet. 

La suppression des appels setAdapter(...) redondants l’a corrigé.

9
vir us

Vous pouvez le faire d'une autre manière, comme ceci 

int position = scrollView.getSelectedItemPosition();
notifyDataSetChanged();
scrollView.setSelection(position);
5
Abhishek Shukla

Si votre adaptateur sous-classe ArrayList, l'appel de adapter.clear() appellera notifyDataSetChanged(), entraînant ainsi la perte de la position de défilement. Pensez à appeler d'abord setNotifyOnChange(false) pour éviter cela.

Plus d'informations ici: https://stackoverflow.com/a/14719538/383761

2
Hugh Jeffner

La réponse de @ Yarth a aidé Je vais juste ajouter un petit problème que je viens de trouver qui a causé cela, Si vous appelez

listview.setVisibility(View.VISIBLE);

fera également défiler la liste entière vers le haut.

0
Lee Boon Kong