2012-06-28 14 views
17

Estoy usando un GridView para mostrar un conjunto de categorías que el usuario puede elegir. Cada elemento de la cuadrícula está compuesto por ImageView y TextView, ambos recuperados del servidor. Cuando se toca un elemento, se inicia otra actividad.Elementos dentro de GridView que se repiten cuando la pantalla se desplaza

Pensé que todo iba bien, hasta que noté que algunos ítems se repetían cuando me desplazo por la pantalla. Cada vez que me desplazo hacia abajo a través de la cuadrícula, y luego hacia atrás, itens cambia su posición y se duplica. Pero incluso cuando toco los itens en mal estado, los valores adecuados se envían a la siguiente actividad.

Al buscar en LogCat, se produce cualquier solicitud repetida al servidor. De hecho, lo he entendido mientras se desplaza:

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 

Parece que cada vez que me desplazo, Ítenes conseguir volver a dibujar ...

ACTUALIZACIÓN: Sólo redibujar ítems en la primera vez que desplazarse por la GridView. Después de esto, todos los itens, incluidos los repetidos, se mantienen en sus lugares.

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

clase 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> 

xml gridview

<?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" 
/> 

Vi otras preguntas sobre este mismo problema, pero ninguna respondió. ¿Alguna idea de lo que está pasando?

+0

Use ViewHolder es una buena práctica del código –

Respuesta

82

Es normal que se ven los mismos elementos que se desplaza por la GridView porque en el método getView configurar los dibujables para el ImageView sólo cuando el convertView es null (por ejemplo, para los primeros elementos que se ven cuando el GridView aparecen en la pantalla). Si el convertView no es null, lo que significa que tiene una vista de fila reciclada, no establece la imagen correcta y permanece con la imagen que se configuró previamente en esta vista reciclada. Tratar de modificar el método getView así:

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

Al hacer clic en un elemento que muestra los elementos correctos porque se utiliza el parámetro position para recuperar los datos.

+0

¡Eso funcionó!Aunque LogCat sigue mostrando esas líneas GC_EXTERNAL_ALLOC cuando me desplazo por primera vez por la cuadrícula ... –

+1

@LucasJota Ese es el recolector de basura, creo que es normal (si no hace que el 'GridView' se demore). Tenga en cuenta que está consultando esas imágenes y también las mantiene en la memoria (no sé cuántas tiene). – Luksprog

+0

Funcionó perfectamente para mí con Button + Textview – KNU

0

cambio aquí y vuelve a intentarlo,

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

¿Por qué agregaría un cheque adicional? Mientras que ya verificamos convertview == null, pondría el último bloque en else block. – Gripsoft

+0

Sí, tienes razón, pero no funcionó en la "declaración de otro" para mí de alguna manera, no estoy seguro. – osayilgan

2

Estos es mi código de GirdView con el botón + 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

Enviar y gridview o vista de lista y en el constructor poner en práctica este método aplicar onscroll oyente

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"); 
     } 
    }); 
Cuestiones relacionadas