Comment fonctionne le mécanisme de recyclage de ListView?

J’ai donc ce problème que j’avais auparavant et naturellement, j’ai demandé de l’aide ici . La réponse de Luksprog était géniale car je n’avais aucune idée de la façon dont ListView et GridView s’optimisaient avec les vues de recyclage. Donc, avec ses conseils, j’ai pu changer la façon dont j’ai ajouté Views à mon GridView. Le problème est maintenant que j’ai quelque chose qui n’a pas de sens. Ceci 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().getDisplayMesortingcs()), 1.0f); params.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMesortingcs()); params.bottomMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMesortingcs()); 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().getDisplayMesortingcs()), 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 est quand je fais défiler, cela se produit, et pas sur la position 0 … Ressemble à la position 6 et à la position 8, plus il met deux en position 8. Maintenant j’essaie toujours d’obtenir le coup d’utiliser ListView et GridView donc je fais Je ne comprends pas pourquoi cela se produit. L’une des principales raisons pour lesquelles je pose cette question est d’aider d’autres personnes qui ne connaissent probablement pas la vue de recyclage de ListView et GridView, ou la façon dont cet article le définit, le mécanisme ScrapView.

entrer la description de l'image ici

Plus tard modifier

L’ajout d’un lien vers une discussion sur Google IO est essentiellement tout ce dont vous avez besoin pour comprendre le fonctionnement de ListView. Link était mort dans les commentaires. Donc, user3427079 était assez sympa pour mettre à jour ce lien. Ici, c’est pour un access facile.

Au début, je n’étais pas non plus au courant du recyclage de listview et du mécanisme d’utilisation de convertview, mais après une journée entière de recherche, je comprends à peu près tous les mécanismes de la vue en liste en faisant référence à une image de android.amberfog. entrer la description de l'image ici

Chaque fois que votre listview est remplie avec un adaptateur, elle affiche essentiellement le nombre de lignes que la listview peut afficher à l’écran et le nombre de lignes ne s’augmente pas même si vous faites défiler la liste. et rapide, Maintenant, l’histoire interne de listview se référant à une image comme vous pouvez le voir initialement a 7 éléments visibles, si vous faites défiler vers le haut lorsque l’object 1 n’est plus visible, getView () transmet cette vue à recycleur. utilisation

 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); ViewHolder holder; 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 que dans votre logcat, au départ, convertview est nul pour toutes les lignes visibles, car il n’y avait initialement aucune vue (item) dans recycleur, donc votre getView () crée chaque nouvelle vue pour les éléments visibles, mais au moment où vous faites défiler votre élément 1 enverra au Recycler avec lui l’état (par exemple, le texte TextView et, comme dans le cas de la mine, si la case est cochée, il sera également associé à la vue et stocké dans le recycleur). Maintenant, lorsque vous faites défiler votre liste vers le haut ou vers le bas ne va pas créer une nouvelle vue, elle utilisera la vue (vue de conversion) qui se trouve déjà dans votre recycleur. Dans Logcat, vous remarquerez que convertView n’est pas nul. 8 sera dessiné en utilisant convertview, c.-à-d., Il prend essentiellement la vue item1 du recycleur et gonfleur à la place de l’article 8, et vous pouvez l’observer comme dans le code de mine si vous aviez une case à cocher et disons que item1 a aussi une case à cocher et que vous l’avez cochée) alors lorsque vous faites défiler, vous verrez que la case à cocher item 8 est déjà cochée, c’est pourquoi viewview utilise la même vue sans créer de nouvelles en raison de l’optimisation des performances.

Choses importantes

1 . Ne définissez jamais layout_height et layout_width de votre wrap_content sur wrap_content car getView() forcera votre adaptateur à demander à un enfant de mesurer la hauteur des vues à afficher dans une vue de liste et peut provoquer des comportements inattendus comme retourner convertview même si la liste n’est pas match_parent utilise match_parent ou fixed width / height.

2 . Si vous souhaitez utiliser une mise en page ou une vue après votre affichage de liste et votre question, si vous définissez layout_height sur fill_parent la vue après l’affichage de la liste ne s’affichera plus à l’écran, il est donc préférable de mettre votre listview dans un layout.Par exemple Linear Layout, définissez la hauteur et la largeur de cette disposition en fonction de vos besoins et définissez l’atsortingbut height and width de votre listview à partir de votre layout (comme si la largeur de votre layout est 320 et la hauteur 280), votre listview devrait avoir la même hauteur et la même largeur . Cela indiquera à getView () la hauteur et la largeur exactes des vues à afficher, et getView () n’appelera pas encore et encore des lignes aléatoires, et d’autres problèmes, comme le retour de la vue de conversion avant même que le défilement ne se produise. ceci, à moins que mon listview ne soit à l’intérieur du lineaLayout, il avait aussi des problèmes comme répéter l’appel de vue et convertir l’affichage, en plaçant Listview dans LinearLayout fonctionnait comme de la magie pour moi (ne savait 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 c’est résolu, je sais, je ne suis pas très bon pour expliquer mais comme je mets toute ma journée à comprendre alors je pensais que d’autres débutants comme moi peuvent obtenir de l’aide de mon expérience et j’espère que maintenant vous comprendrez un peu du framework ListView comment cela fonctionne, car il est vraiment désordonné et délicat alors les débutants ont trouvé trop de problèmes pour le comprendre

Attention, dans le pattern Holder, si vous définissez le post dans votre object Holder, vous devez le 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.. 

En utilisant le modèle de support, vous pouvez obtenir ce que vous voulez:

Vous pouvez trouver la description de ce modèle ici:

Le recyclage de la vue liste se produit lorsque vous faites défiler l’écran et que les éléments de la vue liste ci-dessus sont masqués. Ils sont réutilisés pour afficher les nouveaux éléments de la liste.