2012-05-20 1 views
7

Ho un GridView in Android che riempio con i dati recuperati da una risorsa xml.
Ad esempio, nel GridView sono presenti 15 elementi ordinati in ordine. L'altezza complessiva supera l'altezza dello schermo, quindi devo scorrere per vedere il resto degli elementi.
Il problema è quando si esegue il backup, l'ordine delle righe invisibili è cambiato. È un comportamento misterioso visto che a volte gli oggetti si scambiano le righe l'uno con l'altro. Ecco il mio metodo getView:Perché gli articoli cambiano ordine allo scorrimento in Android GridView?

public class ImageAdapter extends BaseAdapter { 
     public ImageAdapter(Context c, NodeList cuu) { 
       cu = cuu; 
     } 
     public int getCount() { 
       Log.d("Node Count",cu.getLength()+""); 
       return cu.getLength(); 
     } 
     public Object getItem(int position) { 
       return position; 
     } 
     public long getItemId(int position) { 
       return position; 
     } 
     public View getView(int position, View convertView, ViewGroup parent) { 
       View myView = convertView; 
       if (convertView == null) { 
        Node nd = cu.item(position); 
        Log.d("nodes","Pos: "+(position)+" Name: "+nd.getNodeName()+" Title: "+nd.getAttributes().getNamedItem("title").getTextContent()); 
        int catID = Integer.parseInt(nd.getAttributes().getNamedItem("id").getTextContent()); 
        LayoutInflater li = getLayoutInflater(); 
        myView = li.inflate(R.layout.grid_item, null); 
        ImageView imageView = (ImageView) myView.findViewById(R.id.grid_item_image); 
        myView.setLayoutParams(new GridView.LayoutParams(70, 100)); 
        id.download(nd.getAttributes().getNamedItem("icon").getTextContent(),imageView); 
        TextView textView = (TextView) myView.findViewById(R.id.grid_item_text); 
        textView.setText(nd.getAttributes().getNamedItem("title").getTextContent()); 
        myView.setTag((Object) catID); 
       }else{ 
        //Log.d("nodes","Pos: "+(position)); 
       } 
       return myView; 
     } 
     private NodeList cu = null; 
    } 

Aggiornamento: Beh, è ​​piuttosto strano. Dopo un po 'di debug ho notato che nel GridView, l'adapter salta la 13a posizione, il che significa che restituisce 1 invece di 13 e poi passa a 14 !!! (Immagino che il 13 sia sfortuna!)

+0

'Adapter' non salterà le posizioni da solo. Pubblica il codice completo per il tuo adattatore. – Luksprog

+0

Va bene, ho messo l'intero adattatore lì. –

risposta

5

Se questo è tutto il codice che avete nel metodo getView non sei attuazione destra:

public View getView(int position, View convertView, ViewGroup parent) { 
     View myView = convertView; 
     if (myView == null) {   
      Node nd = cu.item(position); 
      int catID = Integer.parseInt(nd.getAttributes().getNamedItem("id") 
        .getTextContent()); 
      LayoutInflater li = getLayoutInflater(); 
      myView = li.inflate(R.layout.grid_item, null); 
      myView.setLayoutParams(new GridView.LayoutParams(70, 100));   
      myView.setTag((Object) catID); 
     } 
     Node nd = cu.item(position); 
     Log.d("nodes", "Pos: " + (position) + " Name: " + nd.getNodeName() 
       + " Title: " 
       + nd.getAttributes().getNamedItem("title").getTextContent()); 
     ImageView imageView = (ImageView) myView 
       .findViewById(R.id.grid_item_image); 
     id.download(nd.getAttributes().getNamedItem("icon") 
       .getTextContent(), imageView); 
     TextView textView = (TextView) myView 
       .findViewById(R.id.grid_item_text); 
     textView.setText(nd.getAttributes().getNamedItem("title") 
       .getTextContent()); 
     return myView; 
    } 

Non so se il codice sopra funziona, il vostro è un po 'strano. Ad ogni modo, penso che il comportamento che vedi sia normale perché tutto ciò che fai nell'adattatore sta popolando i primi elementi visibili e quindi l'adattatore riutilizzerà gli stessi stesso elemento quando scorri verso l'alto e verso il basso a causa del riciclo. Nella getView è necessario:

  • Controllare se il convertView è null:
    • Se è null è il momento di gonfiare una nuova View per questo elemento GridView s'. È inoltre possibile utilizzare il modello di supporto per memorizzare nella cache il numero Views (invece di cercare con findViewById ogni volta) (Si utilizza l'elemento setTag per la visualizzazione gonfiata ma si tratta di un dato dall'elemento Node?!? Che cosa si pianifica? a che fare con esso?!?)
    • Se non è null farete nulla (o se si implementa il modello di supporto che si otterrebbe il tag con il già cercato Views)

e questo è ciò che si dovrebbe fare nel senso che se/else

  • Dopo la parte sopra potrai popolare il Views con i dati (in modo da tenere i dati appropriato per quella posizione).
+0

Grazie, sono totalmente nuovo alla programmazione Android. Con il tuo aiuto potrei farlo funzionare. –

+1

ty! mi hai salvato un giorno – Spyros

3

L'implementazione dell'adattatore è fatalmente imperfetta.

In getView(), se convertView è null, si gonfia un layout e si popolano i suoi widget. Questo va bene.

In getView(), se convertView non è null, non si fa assolutamente nulla. Questo è estremamente sbagliato.

Che cosa si dovrebbe essere facendo in getView(), se convertView non è null, è ancora popolano i widget della cellula. convertView rappresenta una cella da riciclare, quindi puoi saltare l'inflazione e risparmiare tempo CPU, ma devi ancora aggiornare i widget di quella cella per riflettere la posizione che dovresti impostare in questa specifica chiamata getView().

+0

ho lo stesso problema ma ho applicato ViewHolder, e ancora il mio ordine delle immagini stava cambiando. – Mikey

+0

@CommonsWare È vero che tutte le azioni compreso 'findViewById()' devono essere eseguite all'esterno se/else? Qualcuno ha dichiarato che qui e questa informazione è nuova per me. – sandalone

+1

@sandalone: ​​in ** ogni chiamata a 'getView()' è necessario configurare la riga **. I costrutti 'if' /' else' che usi, se ce ne sono, sono a te, fintanto che su molto call a 'getView()' tu configuri completamente la riga. Nel caso dell'OP, l'OP * non * stava configurando la riga se 'convertView' non era' null'. – CommonsWare

10
public View getView(int position, View convertView, ViewGroup parent) { 
    View view; 
    if (convertView == null) { 
     view= inflate your xml 
    } else { 
     view=convertView; 
    } 
    // all remaining code like 
    // view.findViewById(R.id.btn).setText("MyButton");        
    // must be outside if-else 
} 
1

ho appena eliminato il

if(convertView==null) 

funziona

0

Ho usato questa soluzione, sulla base di un altro campione, e ha lavorato:

public View getView(int position, View convertView, ViewGroup parent) { 
    View view = null; 
    if (convertView == null) { 
     view = inflate your xml and apply the View Holder pattern 
    } else { 
     view = convertView; 
    } 
    // retrieve the object by Holder pattern 
    // extra code here 
} 
1

Se la griglia l'articolo contiene diverse visualizzazioni è possibile utilizzare i metodi getTag() e setTag(). In questo caso, gli elementi della griglia non cambieranno più le loro posizioni sullo scorrimento e le prestazioni continueranno a essere corrette:

public class SomeAdapter extends BaseAdapter { 

    public static class ViewHolder { 
     public TextView tvTitle; 
     public ImageView imgPoster; 
    } 

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

     ViewHolder grid; 
     LayoutInflater inflator = activity.getLayoutInflater(); 

     if (convertView == null) { 
      grid = new ViewHolder(); 
      convertView = inflator.inflate(R.layout.grid_item, null); 
      grid.tvTitle = (TextView) convertView.findViewById(R.id.tv_title); 
      grid.imgPoster = (ImageView) convertView.findViewById(R.id.img_poster); 

      convertView.setTag(grid); // <<-- H E R E 
     } else { 
      grid = (ViewHolder) convertView.getTag(); // <<-- H E R E 
     } 
     grid.tvTitle.setText(dataItem.getTitle()); 
     grid.imgPoster.setImage(dataItem.getImage()); 
     return convertView; 
    } 
}