154 votes

Comment fonctionne le mécanisme de recyclage de ListView

Donc, j'ai ce problème que j'avais avant, et, naturellement, j'ai demandé de l'aide sur ici. Luksprog réponse était génial parce que je n'avais aucune idée sur la façon ListView et GridView optimisé avec le recyclage des points de Vue. Donc, avec ses conseils, j'ai pu changer la façon dont j'ai ajouté des points de Vue à mon GridView. Le problème est maintenant, j'ai quelque chose qui n'a pas de sens. C'est mon getView de mon BaseAdapter:


public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            convertView = inflater.inflate(R.layout.day_view_item, parent, false);
        }
        Log.d("DayViewActivity", "Position is: "+position);
        ((TextView)convertView.findViewById(R.id.day_hour_side)).setText(array[position]);
        LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.day_event_layout);

        //layout.addView(new EventFrame(parent.getContext()));

        TextView create = new TextView(DayViewActivity.this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics()), 1.0f);
        params.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        params.bottomMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        create.setLayoutParams(params);
        create.setBackgroundColor(Color.BLUE);
        create.setText("Test"); 
        //the following is my original LinearLayout.LayoutParams for correctly setting the TextView Height
        //new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()), 1.0f)   
        if(position == 0) {
            Log.d("DayViewActivity", "This should only be running when position is 0. The position is: "+position);
            layout.addView(create);
        }

        return convertView;
    }

}

Le problème, c'est quand je scroll, ce qui se passe, et non pas sur la position 0... Ressemble à la position 6 et la position 8, plus il en met deux dans la position 8. Maintenant, je suis encore à essayer d'obtenir le coup de l'utilisation de la ListView et GridView donc je ne comprends pas pourquoi ce qui se passe. L'une des principales raisons pour lesquelles je fais cette question est d'aider les autres qui ne le savez probablement pas sur ListView et GridView de recyclage de Vue, ou de la façon dont cet article met, ScrapView mécanisme.

enter image description here

Éditer Plus Tard

Ajout d'un lien vers google IO parler qui est essentiellement tout ce que vous devez comprendre comment la ListView œuvres. Le lien était mort dans les commentaires. Donc user3427079 a été assez gentil pour mettre à jour le lien. Ici, il est facile d'accès.

340voto

Muhammad Babar Points 1963

Au départ, j'ai également conscience de listview recyclage et la convertview utilisation du mécanisme, mais après des jours de recherche j'ai assez bien comprendre les mécanismes de l'affichage de la liste en se référant à une image à partir d' android.amberfog enter image description here

Si jamais votre liste est rempli avec un adaptateur, il présente le nombre de Lignes que la liste peut afficher sur l'écran et le nombre de lignes n'ya pas augmenter même vous faites défiler la liste, c'est l'astuce android utiliser de sorte que listview travail plus efficace et rapide, Maintenant, l'histoire à l'intérieur de la listview se référant à l'image comme vous pouvez le voir d'abord la vue liste a 7 éléments visibles, si vous faites défiler vers le haut lorsque le point 1 n'est plus visible getView() col de ce point de vue(item 1) à recycler et vous pouvez les utiliser

System.out.println("getview:"+position+" "+convertView);

à l'intérieur de votre

public View getView(final int position, View convertView, ViewGroup parent)
{
    System.out.println("getview:"+position+" "+convertView);
    View row=convertView;
    if(row==null)
    {
        LayoutInflater inflater=((Activity)context).getLayoutInflater();
        row=inflater.inflate(layoutResourceId, parent,false);

        holder=new PakistaniDrama();
        holder.tvDramaName=(TextView)row.findViewById(R.id.dramaName);
        holder.cbCheck=(CheckBox)row.findViewById(R.id.checkBox);

        row.setTag(holder);

    }
    else
    {
        holder=(PakistaniDrama)row.getTag();
    }
            holder.tvDramaName.setText(dramaList.get(position).getDramaName());
    holder.cbCheck.setChecked(checks.get(position));
            return row;
    }

vous remarquerez dans votre logcat initialement convertview est nulle pour toutes les lignes visibles, parce que d'abord il n'y avait aucun point de vue(point) en recycleur, de sorte que votre getView() crée chaque nouvelle vue pour les éléments visibles, mais à l'instant où vous le faites défiler jusqu'à votre point 1 de l'envoyer à l' Recycleur avec l'état(par exemple le TextView texte et comme dans la mienne cas si la case est cochée, il sera également associé avec le point de vue et de les stocker dans recycleur). Maintenant, lorsque vous faites défiler vers le haut/vers le bas de votre listview ne va pas créer un nouveau point de vue, il va utiliser la vue(conversion de vue) qui est déjà dans votre recycleur, dans votre Logcat vous remarquerez que convertView n'est pas nul, c'est parce que le nouvel article 8 sera dessiné à l'aide de convertview, c'est à dire, en gros, c'prendre la item1 vue de les recycler et de inflater en lieu et place de l'article 8 de la et vous pouvez observer que, comme dans la mine de code si vous avait une case à cocher et si vous vérifiez à la position 0(disons item1 a aussi une case à cocher et vous le vérifier) donc, quand vous faites défiler vers le bas vous allez voir point 8 case est déjà cochée, c'est pourquoi listview est de nouveau en utilisant le même point de vue, ne pas en créer un nouveau pour vous en raison de l'optimisation de la performance.

Des choses importantes

1. Ne placez jamais l' layout_height et layout_width de votre listview wrap_content comme getView() force de votre carte pour obtenir un enfant pour la mesure de la hauteur des points de vue à être établi dans la vue liste, et peut provoquer certains comportements inattendus comme une sorte de retour convertview même la liste n'est pas défilé.toujours utiliser match_parent ou fixe largeur/hauteur.

2. Si vous souhaitez utiliser certaines de Mise en page ou de la vue après votre liste d'affichage et question sont venus dans votre l'esprit si j'ai mis l' layout_height de fill_parent le point de vue après l'affichage de la liste ne s'affiche pas comme il va en bas de l'écran, donc de son mieux pour mettre votre listview à l'intérieur d'une mise en page.Par exemple Linéaire, Mise en page et définissez la hauteur et la largeur de cette disposition que de vos besoins et de faire de la hauteur et la largeur de l'attribut de votre listview pour que votre mise en page(comme si votre mise en page en largeur est de 320 et la hauteur est de 280) puis votre listview doivent avoir la même hauteur et largeur. Ceci va dire getView() de hauteur et de largeur de vues à être rendus, et getView() de ne pas appeler de nouveau et de nouveau quelques lignes aléatoires, et d'autres problèmes, comme le retour de convertir vue avant même le défilement ne se produira pas, j'ai tester moi-même, à moins que mon listview était à l'intérieur de la lineaLayout il a aussi des problèmes comme la répétition de l'affichage et de convertir de la vue et que, mettant Listview à l'intérieur de LinearLayout travaillé comme de la magie pour moi.(ne sais pas pourquoi)

01-01 14:49:36.606: I/System.out(13871): getview 0 null
01-01 14:49:36.636: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.636: I/System.out(13871): getview 1 android.widget.RelativeLayout@406082c0
01-01 14:49:36.646: I/System.out(13871): getview 2 android.widget.RelativeLayout@406082c0
01-01 14:49:36.646: I/System.out(13871): getview 3 android.widget.RelativeLayout@406082c0
01-01 14:49:36.656: I/System.out(13871): getview 4 android.widget.RelativeLayout@406082c0
01-01 14:49:36.666: I/System.out(13871): getview 5 android.widget.RelativeLayout@406082c0
01-01 14:49:36.666: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.696: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.706: I/System.out(13871): getview 1 null
01-01 14:49:36.736: I/System.out(13871): getview 2 null
01-01 14:49:36.756: I/System.out(13871): getview 3 null
01-01 14:49:36.776: I/System.out(13871): getview 4 null

Mais maintenant, sa résolu, je sais, je ne suis pas bon à expliquer, mais comme j'ai mis toute ma journée pour comprendre, alors j'ai pensé à d'autres débutants comme moi peuvent obtenir de l'aide de mon expérience et j'espère que maintenant les gens vous avez un peu de compréhension de la ListView cadre comment il fonctionne, c'est vraiment salissant et difficile pour que les débutants trouvé trop de problème de compréhension

8voto

Prenez garde, dans le modèle Titulaire, si vous définissez la position dans votre objet Titulaire, vous devez la définir à chaque fois, par exemple:

 @Override
public final View getView(int position, View view, ViewGroup parent) {
    Holder holder = null;
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) App.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(getContainerView(), parent, false);
        holder = getHolder(position, view, parent);
        holder.setTag(tag);
        view.setTag(holder);
    } else {
        holder = (Holder) view.getTag();
    }
    holder.position = position;
    draw(holder);
    return holder.getView();
}
 

c'est un exemple d'une classe abstraite, où

 getHolder(position, view, parent);
 

fait toutes les opérations de réglage pour le

 ImageViews, TextViews, etc..
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X