Items inside GridView getting repeated when screen scrolls

22,461

Solution 1

It's normal that you see the same items as you scroll down the GridView because in the getView method you set the drawables for the ImageView only when the convertView is null(for example for the first elements that are seen when the GridView appear on the screen). If the convertView is not null, meaning you have a recycled row view, you don't set the correct image and you remain with the image that was previously set on this recycled view. Try to modify the getView method like this:

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

Clicking an element shows you the correct items because you use the position parameter to retrieve the data.

Solution 2

These is my code for GirdView with Button + 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;
    }
Share:
22,461
Lucas Jota
Author by

Lucas Jota

Updated on July 09, 2022

Comments

  • Lucas Jota
    Lucas Jota almost 2 years

    I'm using a GridView to show a set of Categories that user can chose. Each item of the grid is consisted by an ImageView and a TextView, both retrieved from server. When an item is touched, another activity is started.

    I thought everything was going right, until I've noticed that some itens were getting repeated when I scrolls the screen. Whenever I scroll down trough the grid, and then back, itens change itś position and get duplicated. But even when I touch the messed up itens, the right values are send to the next activity.

    Looking in LogCat, any repeated request to server occurs. In fact, I've got this while scrolling:

    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
    

    Looks like everytime I scroll, itens get redraw...

    UPDATE: It only redraw itens on the first time I scroll down the GridView. After this, all itens, including repeated ones, keeps on its places.

    My java class:

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

    imageAdapter class

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

    I saw other questions about this same issue, but none of them answered. Any ideas of what's happening?

  • Lucas Jota
    Lucas Jota almost 12 years
    That worked! Although LogCat keeps displaying those GC_EXTERNAL_ALLOC lines when I first scroll down the grid...
  • user
    user almost 12 years
    @LucasJota That is the garbage collector, I think it's normal(if it doesn't make the GridView laggy). Keep in mind that you're querying for those images and also keeping them in memory(I don't know how many you have).
  • Gripsoft
    Gripsoft almost 12 years
    Why would you add an extra check, while we we already checked for convertview==null, i would put the last block in else block.
  • osayilgan
    osayilgan almost 12 years
    yeah you are right, but it didn't work in the "else statement" for me some how, I'm not sure.
  • ieselisra
    ieselisra about 10 years
    Worked perfectly for me with Button + Textview
  • Monzer Yaghi
    Monzer Yaghi about 9 years
    Thank u very much you're a hero
  • Monzer Yaghi
    Monzer Yaghi over 8 years
  • ArtiomLK
    ArtiomLK over 7 years
    If you add the TextView programmatically. The solution is a little bit different. For example; (Assuming you have a LinearLayout) LinearLayout linearLayout = (LinearLayout)v.findViewById(R.id.NAME_OF_YOUR_LINEARLAYOUT)‌​; linearLayout.removeAllViews(); TextView textViewDay = new TextView(mContext); textViewDay.setText("YOURTEXT"); linearLayout.addView(textViewDay); Therefore, linearLayout.removeAllViews(); would be needed so that you do not end up adding more TextViews on each call to getView(...), which is called every time you scroll up or down
  • Namrata Bagerwal
    Namrata Bagerwal almost 6 years
    Even though I am doing the same, I don't understand why it's not working. Any help would be appreciated.
  • user
    user almost 6 years
    @NamrataBagerwal Please post a new question and provide the code you currently use to get help with the problem you have.