web-dev-qa-db-fra.com

la méthode getView de l'adaptateur de liste de vues personnalisée étant appelée à plusieurs reprises et sans ordre cohérent

J'ai un adaptateur de liste personnalisé:

class ResultsListAdapter extends ArrayAdapter<RecordItem> {

dans la méthode 'getView' surchargée, je fais une impression pour vérifier quelle est la position et s'il s'agit ou non de convertView:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        System.out.println("getView " + position + " " + convertView);

Le résultat de cette opération (lorsque la liste est affichée pour la première fois, aucune entrée de l'utilisateur pour le moment)

04-11 16:24:05.860: INFO/System.out(681): getView 0 null  
04-11 16:24:29.020: INFO/System.out(681): getView 1 Android.widget.RelativeLayout@43d415d8  
04-11 16:25:48.070: INFO/System.out(681): getView 2 Android.widget.RelativeLayout@43d415d8  
04-11 16:25:49.110: INFO/System.out(681): getView 3 Android.widget.RelativeLayout@43d415d8  
04-11 16:25:49.710: INFO/System.out(681): getView 0 Android.widget.RelativeLayout@43d415d8  
04-11 16:25:50.251: INFO/System.out(681): getView 1 null  
04-11 16:26:01.300: INFO/System.out(681): getView 2 null  
04-11 16:26:02.020: INFO/System.out(681): getView 3 null  
04-11 16:28:28.091: INFO/System.out(681): getView 0 null  
04-11 16:37:46.180: INFO/System.out(681): getView 1 Android.widget.RelativeLayout@43cff8f0  
04-11 16:37:47.091: INFO/System.out(681): getView 2 Android.widget.RelativeLayout@43cff8f0  
04-11 16:37:47.730: INFO/System.out(681): getView 3 Android.widget.RelativeLayout@43cff8f0  

Si je ne me trompe pas, getView () n’est appelé que pour les lignes visibles. Étant donné que mon application commence par quatre lignes visibles, au moins les numéros de position compris entre 0 et 3 sont judicieux. Mais le reste est un gâchis:

  • Pourquoi getview est-il appelé pour chaque ligne trois fois? 
  • D'où viennent ces convertViews quand je n'ai pas encore fait défiler?

J'ai fait un peu de recherche, et sans obtenir de bonne réponse, j'ai remarqué que les gens associaient ce problème à des problèmes de mise en page. Donc au cas où, voici la mise en page qui contient la liste:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_height="fill_parent"
    Android:layout_width="fill_parent" 
    Android:orientation="vertical" >

    <TextView Android:id="@+id/pageDetails"
        Android:layout_width="fill_parent" 
        Android:layout_height="wrap_content" />

    <ListView Android:id="@+id/list"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content" 
        Android:drawSelectorOnTop="false" />

</LinearLayout>

et la disposition de chaque ligne individuelle:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="108dp"    
Android:padding="4dp">

<ImageView
    Android:id="@+id/thumb"        
    Android:layout_width="120dp"
    Android:layout_height="fill_parent"        
    Android:layout_alignParentTop="true"
    Android:layout_alignParentBottom="true"
    Android:layout_alignParentLeft="true"
    Android:layout_marginRight="8dp"        
    Android:src="@drawable/loading" />

<TextView  
    Android:id="@+id/price"
    Android:layout_width="wrap_content"
    Android:layout_height="18dp"         
    Android:layout_toRightOf="@id/thumb"
    Android:layout_alignParentBottom="true"       
    Android:singleLine="true" />

<TextView  
    Android:id="@+id/date"
    Android:layout_width="wrap_content"
    Android:layout_height="18dp"         
    Android:layout_alignParentBottom="true"
    Android:layout_alignParentRight="true" 
    Android:paddingRight="4dp"       
    Android:singleLine="true" />

<TextView
    Android:id="@+id/title"
    Android:layout_width="fill_parent"
    Android:layout_height="wrap_content"
    Android:textSize="17dp" 
    Android:layout_toRightOf="@id/thumb"
    Android:layout_alignParentRight="true"
    Android:layout_alignParentTop="true"
    Android:paddingRight="4dp"   
    Android:layout_alignWithParentIfMissing="true"
    Android:gravity="center" />

</RelativeLayout>

Merci pour votre temps

154
edzillion

Ce n'est pas un problème, il n'y a absolument aucune garantie sur l'ordre dans lequel getView() sera appelé ni combien de fois. Dans votre cas particulier, vous faites la pire chose possible avec un ListView en lui donnant un height=wrap_content. Ceci oblige ListView à mesurer quelques enfants hors de l'adaptateur au moment de la mise en page, pour connaître sa taille. C’est ce qui fournit à ListView le convertViews que vous voyez passé à getView() avant même de faire défiler.

263
Romain Guy

Essayez avec match_parent sur la propriété layout_height de la vue liste. Cela empêchera getView() d'être appelé si souvent.

53
Fred T

Je me suis débarrassé de ce problème lorsque j'ai changé à la fois layout_width et layout_height en match_parent (modifier uniquement layout_height n'a pas aidé).


Note utile surveillez si vous avez des éléments imbriqués. Vous devez remplacer le "plus élevé" par match_parent . J'espère que ça aide quelqu'un.

45
Eugene Chumak

Je ne suis pas en mesure de répondre à votre question "Pourquoi" mais j'ai définitivement une solution au problème du problème irritant "ListView répétant" (si vous avez dans votre collection des éléments dépassant la hauteur de l'écran).

Comme beaucoup de personnes ci-dessus l'ont mentionné, conservez la propriété Android: layout_height de la balise ListVew sous la forme fill_parent.

Et à propos de la fonction getView (), la solution consiste à utiliser une classe statique appelée ViewHolder. Découvrez ceci exemple. Il réussit à ajouter tous les éléments de votre tableau Array ou ArrayCollection.

J'espère que ça aide les amis !!

Cordialement, Siddhant

7
Siddhant

Ques: Pourquoi Adaptor appelle-t-il plusieurs fois getView ()? quel adaptateur a besoin d’obtenir des vues en appelant getView ().

Ques: Pourquoi appelle-t-il moins si listview width et height sont définis sur fill_parent? rendre les vues sur l'écran.

J'espère que cela résoudra votre requête.

4
jitain sharma

J'avais le même problème avec la liste déroulante dans un AutoCompleteTextView. Je me suis battu avec le problème pendant deux jours jusqu'à ce que j'arrive ici et que vous me montriez la solution.

Si j'écris dropDownHeight = "match_parent", le problème est résolu. Maintenant, le problème est lié à l'interface utilisateur (lorsque vous avez un élément, la liste déroulante est trop grande), mais le problème des appels multiples (beaucoup plus important) est résolu.

Je vous remercie!!

3

J'ai le même problème. Si height est défini sur fill_parent, j'obtiens "généralement" deux appels par ligne. Mais si je règle la hauteur de mon ListView sur la valeur exacte, par exemple 300 dp, je reçois exactement un appel GetView par ligne. 

Il me semble donc que le seul moyen est d’abord de déterminer la hauteur de l’écran, puis de définir par programme la hauteur de listvilew à cette valeur. Je n'aime pas ça J'espère qu'il y a un meilleur moyen.

2
bobetko

"Pourquoi getview est-il appelé pour chaque ligne trois fois?" Parce que getView est appelé lorsque vous faites défiler listview et mieux dire qu’il est appelé lorsque la position d’une vue de votre liste est modifiée!

2
Ungureanu Liviu

Pour tous ceux qui encore (après avoir défini la height de la ListView sur match_parent) sont bloqués (comme je l'étais):

Vous devez également définir height de la présentation parente sur match_parent.

Voir exemple ci-dessous. La LinearLayout est le parent ici:

<LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical">

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:text="@string/something" />

        <ListView
            Android:id="@+id/friendsList"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent" />
    </LinearLayout>
2
B001ᛦ

j'ai fait cette solution, n'est peut-être pas la meilleure, mais fait le travail ...

//initialize control string
private String control_input = " ";

alors =

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

    View gridview = convertView;

    // change input_array for the array you use
    if (!control_input.equals(input_array[position])) {
        control_input = input_array[position];

        //do your magic

    } 

    return gridview;
}

j'espère que ça aide!

0
yago

Cela arrive peut-être tard, mais si vous utilisez layout_weight, n'oubliez pas de toujours définir layout_width="0dp"

0
Kuti Gbolahan