2012-06-28 3 views
17

Я использую GridView для отображения набора категорий, которые пользователь может выбрать. Каждый элемент сетки состоит из ImageView и TextView, которые извлекаются с сервера. Когда элемент затронут, запускается другое действие.Элементы внутри GridView, повторяющиеся при прокрутке экрана

Я думал, что все идет правильно, пока я не заметил, что некоторые иены повторяются при прокрутке экрана. Всякий раз, когда я прокручиваю вниз по сетке, а затем обратно, itens меняет ее положение и дублируется. Но даже когда я прикасаюсь к испорченному, правильные значения отправляются на следующую активность.

Глядя в LogCat, происходит любой повторный запрос на сервер. На самом деле, у меня есть это во время прокрутки:

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 

Похоже, каждый раз я прокручивать, itens получить перерисовывать ...

UPDATE: Это только перерисовывать itens на первый раз прокручивать вниз GridView. После этого все иены, в том числе повторяющиеся, остаются на своих местах.

Мой 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; 
} 

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

Я видел другие вопросы по этому же вопросу, но никто из них не ответил. Любые идеи о том, что происходит?

+0

Use ViewHolder - хорошая практика кода –

ответ

82

Это нормально, что вы видите одни и те же элементы, как вы прокрутите вниз GridView, потому что в методе getView вы устанавливаете вводимый коэффициент для ImageView только тогда, когда convertView является null (например, для первых элементов, которые видны, когда GridView появляется на экране). Если convertView не null, то есть у вас есть переработанный вид строки, вы не устанавливаете правильное изображение, и вы остаетесь с изображением, которое ранее было установлено на этом переработанном представлении. Попробуйте изменить метод getView так:

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

Щелчок элемента показывает правильные элементы, потому что вы используете параметр position для извлечения данных.

+0

Это сработало!Хотя LogCat продолжает показывать эти строки GC_EXTERNAL_ALLOC, когда я сначала прокручиваю сетку ... –

+1

@LucasJota Это сборщик мусора, я думаю, что это нормально (если он не делает «GridView» лагги). Имейте в виду, что вы запрашиваете эти изображения, а также сохраняете их в памяти (я не знаю, сколько у вас есть). – Luksprog

+0

Работал отлично для меня с Button + Textview – KNU

0

Изменить здесь и попробовать еще раз,

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

Зачем вы добавляете дополнительную проверку, а мы уже проверили для convertview == null, я бы поставил последний блок в блок else. – Gripsoft

+0

Да, вы правы, но это не сработало в «else statement» для меня как-то, я не уверен. – osayilgan

2

Это мой код для GirdView с кнопкой + 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

Отправлять и GridView или ListView и в конструкторе реализации этого метода реализации OnScroll слушатель

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"); 
     } 
    }); 
Смежные вопросы