Comment fonctionne la méthode getView () lors de la création de votre propre adaptateur personnalisé?

101

Mes questions sont:

  1. Quelle est exactement la fonction du LayoutInflater?
  2. Pourquoi tous les articles que j'ai lus vérifient-ils si convertview est nul ou pas en premier? Qu'est-ce que cela signifie quand il est nul et que signifie-t-il quand ce n'est pas le cas?
  3. Quel est le paramètre parent accepté par cette méthode?
GrowinMan
la source

Réponses:

115

1: Le LayoutInflaterprend vos fichiers XML de mise en page et crée différents objets View à partir de son contenu.

2: Les adaptateurs sont conçus pour réutiliser les vues, lorsqu'une vue est défilée de manière à ne plus être visible, elle peut être utilisée pour l'une des nouvelles vues qui apparaissent. Cette vue réutilisée est le convertView. Si ceci est nul, cela signifie qu'il n'y a pas de vue recyclée et que nous devons en créer une nouvelle, sinon nous devrions l'utiliser pour éviter d'en créer une nouvelle.

3: Le parentest fourni pour que vous puissiez gonfler votre vue pour obtenir des paramètres de mise en page appropriés.

Tous ces éléments peuvent être utilisés pour créer efficacement la vue qui apparaîtra dans votre liste (ou une autre vue prenant un adaptateur):

public View getView(int position, @Nullable View convertView, ViewGroup parent){
    if (convertView == null) {
        //We must create a View:
        convertView = inflater.inflate(R.layout.my_list_item, parent, false);
    }
    //Here we can do changes to the convertView, such as set a text on a TextView 
    //or an image on an ImageView.
    return convertView;
}

Notez l'utilisation du LayoutInflater, qui parentpeut être utilisé comme argument, et comment convertViewest réutilisé.

Jave
la source
5
Convertview == null est utile lorsque tous vos itens suivent la même disposition. Lorsque vous devez rechercher une radio ou un bouton coché, par exemple, et modifier la disposition en fonction de chaque élément, vous devez regonfler ou obtenir la vue mise en cache.
sagits le
Pas besoin de trop regonfler. Il vous suffit d'écrire switch ou if-else ladder dans getview et gonfler les vues en fonction de votre cas, remplacer public int getItemViewType (position int) et public int getViewTypeCount (). @sagits
Prashanth Debbadwar
Si les instructions fonctionnent généralement, mais lorsque vous utilisez des boutons radio, modifiez des textes et ce genre de choses, j'ai eu des problèmes avec les vues en cache, il y a quelques questions concernant ce genre de choses sur le débordement de pile.
sagits
71

getView()Procédé adaptateur est de l'avis de génération d'un article ListView, Gallery...

  1. LayoutInflaterest utilisé pour obtenir l'objet View que vous définissez dans un xml de mise en page (l'objet racine, normalement LinearLayout, FrameLayoutou RelativeLayout)

  2. convertViewest pour le recyclage. Disons que vous avez une liste qui ne peut afficher que 10 éléments à la fois, et actuellement il affiche l'élément 1 -> élément 10. Lorsque vous faites défiler un élément vers le bas, l'élément 1 sera hors de l'écran, et l'élément 11 sera affiché . Pour générer la vue pour l'élément 11, la méthode getView () sera appelée, et convertViewvoici la vue de l'élément 1 (qui n'est plus nécessaire). Alors créez plutôt un nouvel objet View pour l'élément 11 (ce qui est coûteux), pourquoi ne pas le réutiliser convertView? => nous vérifions simplement qu'il convertViewest nul ou non, si nul crée une nouvelle vue, sinon réutilise convertView.

  3. parentViewest la ListView ou la Galerie ... qui contient la vue de l'élément qui getView()génère.

Remarque : vous n'appelez pas cette méthode directement, il vous suffit de l'implémenter pour indiquer à la vue parent comment générer la vue de l'élément.

Anh Tuan
la source
2
EXCELLENTE explication pour le parentView, impossible de trouver une meilleure explication que celle-ci, +1
Ahmed Adel Ismail
Explication incroyable!
gabi
grande explication +1
tpk
8

Vous pouvez regarder cette vidéo sur la vue de liste. Il s'agit de Google IO de l'année dernière et reste le meilleur aperçu des vues de liste dans mon esprit.

http://www.youtube.com/watch?v=wDBM6wVEO70

  1. Il gonfle les mises en page (les fichiers xml de votre dossier res / layout /) en objets Java tels que LinearLayout et d'autres vues.

  2. Regardez la vidéo, vous mettra au courant de l'utilisation de la vue convertie, essentiellement une vue recyclée en attente d'être réutilisée par vous, pour éviter de créer un nouvel objet et de ralentir le défilement de votre liste.

  3. Vous permet de référencer votre vue de liste à partir de l'adaptateur.

Erbsman
la source
5

Quelle est exactement la fonction du LayoutInflater?

Lorsque vous concevez à l'aide de XML, tous les éléments de votre interface utilisateur ne sont que des balises et des paramètres. Avant de pouvoir utiliser ces éléments d'interface utilisateur (par exemple, un TextView ou un LinearLayout), vous devez créer les objets réels correspondant à ces éléments xml. C'est à cela que sert le gonfleur. Le gonfleur utilise ces balises et leurs paramètres correspondants pour créer les objets réels et définir tous les paramètres. Après cela, vous pouvez obtenir une référence à l'élément d'interface utilisateur à l'aide de findViewById ().

Pourquoi tous les articles que j'ai lus vérifient-ils si convertview est nul ou pas en premier? Qu'est-ce que cela signifie quand il est nul et que signifie-t-il quand ce n'est pas le cas?

Celui-ci est intéressant. Vous voyez, getView () est appelé à chaque fois qu'un élément de la liste est dessiné. Maintenant, avant que l'élément puisse être dessiné, il doit être créé. Maintenant, convertView est essentiellement la dernière vue utilisée pour dessiner un élément. Dans getView (), vous gonflez d'abord le xml, puis utilisez findByViewID () pour obtenir les différents éléments de l'interface utilisateur de l'élément de liste. Lorsque nous vérifions (convertView == null), ce que nous faisons est de vérifier que si une vue est nulle (pour le premier élément), puis de la créer, sinon, si elle existe déjà, réutilisez-la, pas besoin de recommencer le processus de gonflage . Le rend beaucoup plus efficace.

Vous devez également avoir rencontré un concept de ViewHolder dans getView (). Cela rend la liste plus efficace. Ce que nous faisons, c'est créer une visionneuse et stocker la référence à tous les éléments de l'interface utilisateur que nous avons obtenus après le gonflement. De cette façon, nous pouvons éviter d'appeler les nombreux findByViewId () et gagner beaucoup de temps. Ce ViewHolder est créé dans la condition (convertView == null) et est stocké dans le convertView à l'aide de setTag (). Dans la boucle else, nous le récupérons simplement en utilisant getView () et le réutilisons.

Quel est le paramètre parent accepté par cette méthode?

Le parent est un ViewGroup auquel votre vue créée par getView () est finalement attachée. Maintenant, dans votre cas, ce serait le ListView.

J'espère que cela t'aides :)

Shubhayu
la source
4
  1. L'inflateur de mise en page gonfle / ajoute du XML externe à votre vue actuelle.

  2. getView () est appelé plusieurs fois, y compris lors du défilement. Donc, s'il a déjà une vue gonflée, nous ne voulons pas le refaire car le gonflement est un processus coûteux ... c'est pourquoi nous vérifions si sa valeur est nulle et puis le gonflons.

  3. La vue parente est une seule cellule de votre liste.

ngesh
la source
3
La vue parente n'est pas expliquée correctement ici. Ce sera le ListView pas le ListItem
Varun Jain
2

LayoutInflaterest utilisé pour générer des vues dynamiques du XML pour l' ListViewélément ou dans onCreateViewle fragment.

ConvertViewest essentiellement utilisé pour recycler les vues qui ne sont pas dans la vue actuellement. Disons que vous avez un scrollable ListView. En défilant vers le bas ou vers le haut, convertViewdonne la vue qui a été défilée. Cette réutilisation économise de la mémoire.

Le paramètre parent de la getView()méthode donne une référence à la disposition parent qui a la listView. Supposons que vous souhaitiez obtenir l'ID de tout élément du XML parent que vous pouvez utiliser:

ViewParent nv = parent.getParent();

while (nv != null) {

    if (View.class.isInstance(nv)) {
        final View button = ((View) nv).findViewById(R.id.remove);
        if (button != null) {
            // FOUND IT!
            // do something, then break;
            button.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Log.d("Remove", "Remove clicked");

                    ((Button) button).setText("Hi");
                }
            });
        }
        break;
    }

 }
user936414
la source
1

getView()méthode create new Viewou ViewGrouppour chaque ligne de Listviewou Spinner. Vous pouvez définir ceci Viewou ViewGroupdans un Layout XMLfichier dans un res/layoutdossier et pouvez lui donner la référenceAdapter classe Object.

si vous avez 4 éléments dans un tableau transmis à l'adaptateur. getView()La méthode créera 4 vues pour 4 lignes d'Adaper.

La classe LayoutInflater a une méthode inflate () qui crée un objet de vue à partir d'une mise en page de ressources XML.

Ravi1187342
la source
0

Vous pouvez également trouver des informations utiles sur getView dans l'interface de l'adaptateur dans le fichier Adapter.java. Ça dit;

/**
 * Get a View that displays the data at the specified position in the data set. You can either
 * create a View manually or inflate it from an XML layout file. When the View is inflated, the
 * parent View (GridView, ListView...) will apply default layout parameters unless you use
 * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)}
 * to specify a root view and to prevent attachment to the root.
 * 
 * @param position The position of the item within the adapter's data set of the item whose view
 *        we want.
 * @param convertView The old view to reuse, if possible. Note: You should check that this view
 *        is non-null and of an appropriate type before using. If it is not possible to convert
 *        this view to display the correct data, this method can create a new view.
 *        Heterogeneous lists can specify their number of view types, so that this View is
 *        always of the right type (see {@link #getViewTypeCount()} and
 *        {@link #getItemViewType(int)}).
 * @param parent The parent that this view will eventually be attached to
 * @return A View corresponding to the data at the specified position.
 */
View getView(int position, View convertView, ViewGroup parent);
Hamza Polat
la source