Come funziona il metodo getView () quando si crea il proprio adattatore personalizzato?


101

Le mie domande sono:

  1. Qual è esattamente la funzione del LayoutInflater?
  2. Perché tutti gli articoli che ho letto controllano prima se convertview è nullo o no? Cosa significa quando è nullo e cosa significa quando non lo è?
  3. Qual è il parametro genitore accettato da questo metodo?

Risposte:


115

1: LayoutInflaterprende i file XML del layout e crea diversi oggetti View dal suo contenuto.

2: Gli adattatori sono costruiti per riutilizzare le viste, quando una vista viene fatta scorrere in modo che non sia più visibile, può essere utilizzata per una delle nuove viste che appaiono. Questa vista riutilizzata è la convertView. Se questo è nullo significa che non esiste una View riciclata e dobbiamo crearne una nuova, altrimenti dovremmo usarla per evitare di crearne una nuova.

3: parentviene fornito in modo da poter aumentare la visualizzazione in quella per i parametri di layout corretti.

Tutti questi insieme possono essere utilizzati per creare efficacemente la vista che apparirà nella tua lista (o un'altra vista che richiede un adattatore):

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;
}

Si noti l'uso di LayoutInflater, che parentpuò essere utilizzato come argomento per esso e come convertViewviene riutilizzato.


5
Convertview == null è utile quando tutti i tuoi itens seguono lo stesso layout. Quando è necessario verificare la presenza di una radio o un pulsante selezionato, ad esempio, e modificare il layout in base a ciascun elemento, è necessario gonfiare nuovamente o ottiene la visualizzazione cache.
sagits

Non c'è bisogno di gonfiare troppo. Devi solo scrivere switch o if-else ladder in getview e gonfiare le viste in base al tuo caso, sovrascrivere public int getItemViewType (int position) e public int getViewTypeCount (). @sagits
Prashanth Debbadwar

Se le istruzioni di solito funzionano, ma quando si utilizzano i pulsanti di opzione, si modificano i testi e questo tipo di cose che ho avuto problemi con le viste memorizzate nella cache, ci sono alcune domande riguardanti questa roba in overflow dello stack.
sagits

71

getView()Procedimento adattatore è per vista dell'elemento di generazione di un ListView, Gallery...

  1. LayoutInflaterviene utilizzato per ottenere l'oggetto View, che si definisce in un layout di XML (l'oggetto principale, normalmente LinearLayout, FrameLayouto RelativeLayout)

  2. convertViewè per il riciclaggio. Supponiamo che tu abbia una visualizzazione elenco che può visualizzare solo 10 elementi alla volta, e attualmente sta visualizzando l'elemento 1 -> elemento 10. Quando scorri verso il basso un elemento, l'elemento 1 sarà fuori dallo schermo e l'elemento 11 sarà visualizzato . Per generare la vista per l'elemento 11, verrà chiamato il metodo getView (), ed convertViewecco la vista dell'elemento 1 (che non è più necessario). Quindi, invece, crea un nuovo oggetto Visualizza per l'elemento 11 (che è costoso), perché non riutilizzarlo convertView? => controlliamo semplicemente che convertViewsia nullo o meno, se nullo crea una nuova vista, altrimenti riutilizzalo convertView.

  3. parentViewè ListView o Gallery ... che contiene la vista dell'elemento che getView()genera.

Nota : non chiami questo metodo direttamente, devi solo implementarlo per dire alla vista genitore come generare la vista dell'elemento.


2
ECCELLENTE spiegazione per parentView, non riesco a trovare una spiegazione migliore di questa, +1
Ahmed Adel Ismail

Spiegazione incredibile!
gabi

ottima spiegazione +1
tpk

8

Potresti dare un'occhiata a questo video sulla visualizzazione elenco. È degli ultimi anni Google IO e ancora il miglior walk-through delle visualizzazioni elenco nella mia mente.

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

  1. Gonfia i layout (i file xml nella cartella res / layout /) in oggetti java come LinearLayout e altre viste.

  2. Guarda il video, ti aggiornerà sull'uso della vista di conversione, in pratica è una vista riciclata che aspetta di essere riutilizzata da te, per evitare di creare un nuovo oggetto e rallentare lo scorrimento della tua lista.

  3. Consente di fare riferimento alla visualizzazione elenco dall'adattatore.


5

Qual è esattamente la funzione del LayoutInflater?

Quando si progetta utilizzando XML, tutti gli elementi dell'interfaccia utente sono solo tag e parametri. Prima di poter utilizzare questi elementi dell'interfaccia utente, (ad esempio un TextView o LinearLayout), è necessario creare gli oggetti effettivi corrispondenti a questi elementi xml. Questo è lo scopo del gonfiatore. L'inflater utilizza questi tag e i parametri corrispondenti per creare gli oggetti effettivi e impostare tutti i parametri. Dopodiché puoi ottenere un riferimento all'elemento dell'interfaccia utente utilizzando findViewById ().

Perché tutti gli articoli che ho letto controllano prima se convertview è nullo o no? Cosa significa quando è nullo e cosa significa quando non lo è?

Questo è interessante. Vedete, getView () viene chiamato ogni volta che viene disegnato un elemento nell'elenco. Ora, prima che l'oggetto possa essere disegnato, deve essere creato. Ora convertView è fondamentalmente l'ultima vista utilizzata per disegnare un elemento. In getView () si gonfia prima l'xml e poi si usa findByViewID () per ottenere i vari elementi dell'interfaccia utente dell'elemento list. Quando controlliamo (convertView == null) ciò che facciamo è controllare che se una vista è nulla (per il primo elemento), crearla, altrimenti, se esiste già, riutilizzarla, non è necessario ripetere il processo di gonfiaggio . Lo rende molto più efficiente.

Devi anche aver trovato un concetto di ViewHolder in getView (). Ciò rende l'elenco più efficiente. Quello che facciamo è creare un viewholder e memorizzare il riferimento a tutti gli elementi dell'interfaccia utente che abbiamo ottenuto dopo il gonfiaggio. In questo modo, possiamo evitare di chiamare i numerosi findByViewId () e risparmiare molto tempo. Questo ViewHolder viene creato nella condizione (convertView == null) e viene memorizzato nel convertView utilizzando setTag (). Nel ciclo else lo recuperiamo semplicemente usando getView () e lo riutilizziamo.

Qual è il parametro genitore accettato da questo metodo?

Il genitore è un ViewGroup a cui è infine allegata la vista creata da getView (). Ora nel tuo caso questo sarebbe ListView.

Spero che questo ti aiuti :)


4
  1. Il programma di gonfiaggio del layout gonfia / aggiunge XML esterno alla visualizzazione corrente.

  2. getView () viene chiamato numerose volte, anche durante lo scorrimento. Quindi, se ha già la vista gonfiata, non vogliamo farlo di nuovo poiché il gonfiaggio è un processo costoso .. ecco perché controlliamo se è nullo e poi lo gonfiamo.

  3. La vista genitore è una cella singola del tuo elenco.


3
La vista genitore è spiegata in modo errato qui. Sarà il ListView, non il ListItem
Varun Jain

2

LayoutInflaterviene utilizzato per generare viste dinamiche dell'XML per l' ListViewelemento o in onCreateViewdel frammento.

ConvertViewè fondamentalmente utilizzato per riciclare le viste che non sono attualmente nella vista. Dì che hai uno scrollabile ListView. Scorrendo verso il basso o verso l'alto, convertViewdà la vista che è stata fatta scorrere. Questo riutilizzo consente di risparmiare memoria.

Il parametro padre del getView()metodo fornisce un riferimento al layout padre che ha listView. Supponi di voler ottenere l'ID di qualsiasi elemento nell'XML genitore che puoi utilizzare:

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;
    }

 }

1

getView()metodo crea nuovo Viewo ViewGroupper ogni riga di Listviewo Spinner. Puoi definire questo Viewo ViewGroupin un Layout XMLfile nella res/layoutcartella e puoi dare il riferimento alla Adapterclasse Object.

se hai 4 elementi in un array passati all'adattatore. getView()Il metodo creerà 4 viste per 4 righe di Adaper.

La classe LayoutInflater ha un metodo inflate () che crea View Object dal layout della risorsa XML.


0

È inoltre possibile trovare informazioni utili su getView nell'interfaccia dell'adattatore nel file Adapter.java. Dice;

/**
 * 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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.