2012-06-28 10 views
17

Sto usando un GridView per mostrare un insieme di categorie che l'utente può scegliere. Ogni elemento della griglia è costituito da un ImageView e un TextView, entrambi recuperati dal server. Quando un oggetto viene toccato, viene avviata un'altra attività.Elementi all'interno di GridView che si ripetono quando lo schermo scorre

Ho pensato che tutto andava bene, fino a quando non ho notato che alcuni iten venivano ripetuti quando scorrevo lo schermo. Ogni volta che scorro verso il basso attraverso la griglia, e poi indietro, itens cambia posizione e viene duplicato. Ma anche quando tocco l'itens incasinato, i valori corretti vengono inviati alla prossima attività.

Guardando in LogCat, si verifica qualsiasi richiesta ripetuta al server. In realtà, ho questo durante lo scorrimento:

06-28 12:36:38.554: D/dalvikvm(358): GC_EXTERNAL_ALLOC freed 2061 objects/156024 bytes in 51ms 
06-28 12:36:42.915: D/dalvikvm(358): GC_FOR_MALLOC freed 6590 objects/737528 bytes in 57ms 
06-28 12:38:26.725: D/dalvikvm(358): GC_EXTERNAL_ALLOC freed 5426 objects/468176 bytes in 71ms 
06-28 12:38:26.875: D/dalvikvm(358): GC_EXTERNAL_ALLOC freed 409 objects/17480 bytes in 68ms 

Sembra che ogni volta che scorrere, itens ottenere ridisegnare ...

UPDATE: ridisegnare solo itens la prima volta che ho scorrere verso il basso il GridView. Dopo questo, tutte le itens, comprese quelle ripetute, rimangono al suo posto.

La mia classe Java:

public void proccess(){ 
    int qtdCategorias = json.length(); 
    imagens = new Drawable[qtdCategorias]; 
    categorias = new String[qtdCategorias]; 
    for (int i=0; i<qtdCategorias; i++){ 
     JSONArray c = json.optJSONArray(i); 
     String urlAmigavel = null; 
     String imagemSite = null; 
     String nomeCategoria = null; 
     try { 
      urlAmigavel = c.getString(6); 
      imagemSite = c.getString(3); 
      nomeCategoria = c.getString(2); 
     } catch (JSONException e) { 
      Log.e("CategoriasJogarActivity", e.toString()); 
      e.printStackTrace(); 
     } 
     categorias[i] = nomeCategoria; 
     imagens[i] = getImagem(urlAmigavel, imagemSite); 
    } 


    gridview = (GridView) findViewById(R.id.include3); 

    ImageAdapter imageAdapter = new ImageAdapter(ctx, imagens, categorias); 

    gridview.setAdapter(imageAdapter); 

    gridview.setOnItemClickListener(new OnItemClickListener() { 
     public void onItemClick(AdapterView<?> parent, View v, 
       int position, long id) { 

      String name = null; 
      String idt = null; 
      try { 
       JSONArray c = json.optJSONArray(position); 
       name = c.getString(2); 
       idt = c.getString(0); 
      } catch (JSONException e) { 
       Log.e("CategoriasJogarActivity", 
         "JSONException" + e.toString()); 
      } 

      Intent in = new Intent(getApplicationContext(), 
        JogarActivity.class); 
      in.putExtra(TAG_NAME, name); 
      in.putExtra(TAG_ID, idt); 
      in.putExtra(TAG_PRIMEIRAPERGUNTA, true); 
      startActivity(in); 

     } 
    }); 
} 


public Drawable getImagem(String urlAmigavel, String img) { 
    String url = "http://www.qranio.com/pergunta/" + urlAmigavel + "/"+ img; 
    InputStream is = null; 
    try { 
     URL urlImagem = new URL(url); 
     is = (InputStream) getObjeto(urlImagem); 
    } catch (MalformedURLException e1) { 
     Log.e("CategoriasJogarActivity", e1.toString()); 
     e1.printStackTrace(); 
    } 
    Drawable d = Drawable.createFromStream(is, "src"); 

    return d; 
} 

private Object getObjeto(URL url) { 
    Object content = null; 
    try { 
     content = url.getContent(); 
    } catch (IOException e) { 
     Log.e("CategoriasJogarActivity", e.toString()); 
     e.printStackTrace(); 
    } 
    return content; 
} 

classe imageAdapter

public class ImageAdapter extends BaseAdapter{ 
private Context mContext; 
private final Drawable[] mThumbIds; 
private final String[] mTextIds; 


public ImageAdapter(Context c, Drawable[] d, String[] s) { 
    mContext = c; 
    mThumbIds = d; 
    mTextIds = s; 
} 

public int getCount() { 
    return mThumbIds.length; 
} 

public Object getItem(int position) { 
    return null; 
} 

public long getItemId(int position) { 
    return 0; 
} 

//create a new ImageView for each item referenced by the Adapter 
public View getView(int position, View convertView, ViewGroup parent) { 
    //ImageView imageView; 
    View v; 
    if (convertView == null) { // if it's not recycled, initialize some attributes 
     LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); 
     v = inflater.inflate(R.layout.gridview_item_layout, null); 
     TextView text = (TextView)v.findViewById(R.id.grid_item_text); 
     text.setText(mTextIds[position]); 
     ImageView image = (ImageView)v.findViewById(R.id.grid_item_image); 
     image.setImageDrawable(mThumbIds[position]); 


    } else { 

     v = (View) convertView; 
    } 


    return v; 
} 


} 

gridview_item_layout xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/gridview_item_layout" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:orientation="vertical" 
android:gravity="center_horizontal" > 

<ImageView android:id="@+id/grid_item_image" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:scaleType="fitCenter" 
android:minHeight="100dip" 
android:minWidth="100dip" 
> 
</ImageView> 

<TextView android:id="@+id/grid_item_text" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:text="TextView" 
android:gravity="center" 
android:textColor="#F9A512" 
android:textStyle="bold" 
android:textSize="18dp" 
> 
</TextView> 
</LinearLayout> 

GridView xml

<?xml version="1.0" encoding="utf-8"?> 
<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/gridview" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:numColumns="auto_fit" 
android:verticalSpacing="10dip" 
android:horizontalSpacing="10dip" 
android:stretchMode="columnWidth" 
android:gravity="center" 
android:background="#FFFFFF" 
android:padding="5dip" 
/> 

Ho visto altre domande su questo stesso problema, ma nessuno di loro ha risposto. Qualche idea su cosa sta succedendo?

+0

Usa ViewHolder è una buona pratica del codice –

risposta

82

E 'normale che si vede gli stessi elementi quando scorri il GridView perché nel metodo getView si impostano le drawable per l'ImageView solo quando il convertView è null (ad esempio, per i primi elementi che si vedono quando appaiono i GridView sullo schermo). Se convertView non è null, significa che si dispone di una vista di riga riciclata, non si imposta l'immagine corretta e si rimane con l'immagine precedentemente impostata su questa vista riciclata. Provate a modificare il metodo getView in questo modo:

public View getView(int position, View convertView, ViewGroup parent) { 
    View v; 
    if (convertView == null) { // if it's not recycled, initialize some attributes 
     LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); 
     v = inflater.inflate(R.layout.gridview_item_layout, parent, false); 
    } else { 
     v = (View) convertView; 
    } 
    TextView text = (TextView)v.findViewById(R.id.grid_item_text); 
    text.setText(mTextIds[position]); 
    ImageView image = (ImageView)v.findViewById(R.id.grid_item_image); 
    image.setImageDrawable(mThumbIds[position]); 
    return v; 
} 

Facendo clic su un elemento che mostra gli articoli corretti perché si utilizza il parametro position per recuperare i dati.

+0

Che ha funzionato!Sebbene LogCat continui a visualizzare le righe GC_EXTERNAL_ALLOC quando per prima cosa scorro verso il basso nella griglia ... –

+1

@LucasJota Questo è il garbage collector, penso sia normale (se non rende il 'GridView' laggy). Tieni presente che stai interrogando per quelle immagini e le tenga anche in memoria (non so quanti ne hai). – Luksprog

+0

Ha funzionato perfettamente per me con Button + Textview – KNU

0

cambiamento qui e provare di nuovo,

View v; 
if (convertView == null) { // if it's not recycled, initialize some attributes 
    LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE); 
    v = inflater.inflate(R.layout.gridview_item_layout, null); 
    TextView text = (TextView)v.findViewById(R.id.grid_item_text); 
    text.setText(mTextIds[position]); 


} else { 

    v = (View) convertView; 
} 
if(view!=null) 
     { 
       ImageView image = (ImageView)v.findViewById(R.id.grid_item_image); 
       image.setImageDrawable(mThumbIds[position]); 
       notifyDataSetChanged(); //Calling this helped to solve the problem. 
     } 


return v; 
} 
+0

Perché dovresti aggiungere un controllo extra, mentre abbiamo già controllato per convertview == null, metterei l'ultimo blocco nel blocco else. – Gripsoft

+0

sì, hai ragione, ma non ha funzionato nella "dichiarazione else" per me un po 'come, non sono sicuro. – osayilgan

2

Questi è il mio codice per GirdView con pulsante + TextView

public View getView(final int position, View convertView, ViewGroup parent) { 
     LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     if (convertView == null) { 
      convertView = mInflater.inflate(R.layout.grid_item, null); 
     } else { 
      holder = (ViewHolder) convertView.getTag(); 
     } 
     TextView text = (TextView)convertView.findViewById(R.id.texto_grid); 
     text.setText(app_listaActiva_NOMBRES[position]); 
     Button image = (Button)convertView.findViewById(R.id.miniatura_grid); 
     image.setBackgroundResource(R.drawable.custom_button); 
     image.setOnClickListener(new MyOnClickListener2(position,app_listaActiva_SONIDOS)); 
     return convertView; 
    } 
0

Send e GridView o ListView e nel costruttore implementare questo metodo implementare onscroll ascoltatore

this.mGridView = mGridView; 
    this.mGridView.setOnScrollListener(new OnScrollListener() { 

     @Override 
     public void onScrollStateChanged(AbsListView view, int scrollState) { 
      Log.v("onScrollStateChanged", "onScrollStateChanged"); 
      if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) { 
       isScrollStop = true; 

       notifyDataSetChanged(); 
      } else { 
       isScrollStop = false; 
      } 
     } 

     @Override 
     public void onScroll(AbsListView view, int firstVisibleItem, 
       int visibleItemCount, int totalItemCount) { 
      Log.v("onScroll", "onScroll"); 
     } 
    }); 
Problemi correlati