2014-12-30 2 views
0

Я использую UIL для загрузки изображений с URL-адреса в Gridview, но проблема в том, что изображения и элементы дублируются или загружаются на многие неправильные позиции.Дублирующие элементы в неправильном положении в GridView

Элемент, который находится на полпути от экрана, дублируется.

enter image description here

это GridView адаптер:

public class GridViewAdapter extends BaseAdapter { 

private Activity _activity; 
private ArrayList<Object_Wallpaper> wallpapersList; 
private ImageLoader mImageLoader; 
GridViewAdapter adapter; 
ViewHolder holder; 
Object_Wallpaper wall; 

public GridViewAdapter(Activity activity, ArrayList<Object_Wallpaper> wallpapersList, 
     int imageWidth) { 
    this._activity = activity; 
    this.wallpapersList = new ArrayList<Object_Wallpaper>(); 
    this.wallpapersList = wallpapersList; 
    this.adapter = this; 
    this.mImageLoader = ImageLoader.getInstance(); 
} 

@Override 
public int getCount() { 
    return this.wallpapersList.size(); 
} 

@Override 
public Object getItem(int position) { 
    return wallpapersList.get(position); 
} 

@Override 
public long getItemId(int position) { 
    return position; 
} 

/*private view holder class*/ 
private class ViewHolder { 
    ImageView smallThumb; 
    ProgressBar pb; 
} 

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

    holder = new ViewHolder(); 
    if (convertView == null) { 
     LayoutInflater inflater = _activity.getLayoutInflater(); 
     convertView = inflater.inflate(R.layout.grid_item_photo, null); 
     holder.smallThumb = (ImageView) convertView.findViewById(R.id.imgThumbnail); 
     holder.pb = (ProgressBar) convertView.findViewById(R.id.progressBar1); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 
    wall = wallpapersList.get(position); 

    showImage(position); 

    return convertView; 
} 

private void showImage(final int position){ 
    if(!wall.isDownloaded){ 
     mImageLoader.displayImage(wall.smallURL, holder.smallThumb, null, 
       new ImageLoadingListener() { 

      @Override 
      public void onLoadingStarted(String imageUri, View view) { 
       holder.pb.setVisibility(View.VISIBLE); 
      } 

      @Override 
      public void onLoadingFailed(String imageUri, View view, 
        FailReason failReason) { 
       holder.pb.setVisibility(View.GONE); 
      } 

      @Override 
      public void onLoadingComplete(String imageUri, 
              View view, Bitmap loadedImage) { 
       holder.pb.setVisibility(View.GONE); 
       wall.isDownloaded = true; 
       wallpapersList.set(position, wall); 
      } 

      @Override 
      public void onLoadingCancelled(String imageUri, View view) { 
      } 


     }, new ImageLoadingProgressListener(){ 

      @Override 
      public void onProgressUpdate(String imageUri, View view, 
        int current, int total) { 
       holder.pb.setProgress(Math.round(100.0f * current/total)); 
      } 

     }); 
    } else { 
     mImageLoader.displayImage(wall.smallURL, holder.smallThumb); 
     holder.pb.setVisibility(View.GONE); 
    } 
} 

} 

И это объект:

public class Object_Wallpaper implements Serializable { 
private static final long serialVersionUID = 1L; 
public String id,title,tags,fullResURL, thumbURL, smallURL; 
public boolean isDownloaded; 

public Object_Wallpaper(String id, String title, String tags, 
         String fullResURL, String thumbURL, String smallURL) {  
    this.id = id; 
    this.title = title; 
    this.tags = tags; 
    this.fullResURL = fullResURL; 
    this.thumbURL = thumbURL; 
    this.smallURL = smallURL; 
    this.isDownloaded = false; 
} 
} 

вы можете мне сказать, что вещи я сделал неправильно до сих пор, пожалуйста? Благодарю. Я видел такие же вопросы в другом месте, но они тоже не помогли.

EDIT:

я понял, что это происходит только в быстрой прокрутки. что мне делать?

ответ

0

Java является передачей по ссылке при назначении объектов. В getView методе вы присваиваете новое значение тот же указатель для предыдущих объектов:

wall = wallpapersList.get(position); 

Вы должны создать новый экземпляр каждый раз. Он должен быть изменен на:

wall = new Object_Wallpaper(); 
wall = wallpapersList.get(position); 
2

Проблема заключается в том, что ваш класс адаптера имеет отдельные экземпляры полей (держатель и стена), где вам нужна копия этих переменных для каждого вызова getView. Так как, когда загрузчик изображений заканчивает каждое изображение, это изображение отображается в том случае, когда последний элемент был вызван. Имеет ли это смысл?

Первым шагом является изменение этих полей на локальные переменные в getView и параметры showImage. У вас все еще будут проблемы после этого шага, когда вы прокрутите список вниз, потому что Android попытается переработать ваши представления во время прокрутки, и поэтому, когда загрузчик изображений завершит загрузку изображения для позиции, которая была прокручена вне поля зрения, она будет отображать загруженное изображение в любом положении, в котором его просмотр перерабатывается. Чтобы решить эту проблему, вы можете использовать HashMap (или более эффективный SparseArray), чтобы отслеживать, какие переработанные представления в настоящее время представляют, какие позиции.

private SparseArray<ViewHolder> holderMap = new SparseArray<ViewHolder>(); 
@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 
    if (convertView == null) { 
     holder = new ViewHolder(); 
     LayoutInflater inflater = _activity.getLayoutInflater(); 
     convertView = inflater.inflate(R.layout.grid_item_photo, null); 
     holder.smallThumb = (ImageView) convertView.findViewById(R.id.imgThumbnail); 
     holder.pb = (ProgressBar) convertView.findViewById(R.id.progressBar1); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
     // If recycled, remove the holder's previous position from map 
     int oldPosition = holderMap.indexOfValue(holder); 
     if (oldPosition >= 0) { 
      holderMap.remove(oldPosition); 
     } 
    } 
    // Keep track of which view is representing this position 
    holderMap.put(position, holder); 

    Object_Wallpaper wall = wallpapersList.get(position); 
    showImage(position, holderMap, wall); 

    return convertView; 
} 

private void showImage(final int position, final SparseArray<ViewHolder> holderMap, final Object_Wallpaper wall) { 
    if(!wall.isDownloaded){ 
     mImageLoader.displayImage(wall.smallURL, holder.smallThumb, null, 
       new ImageLoadingListener() { 

      @Override 
      public void onLoadingStarted(String imageUri, View view) { 
       ViewHolder holder = holderMap.get(position); 
       if (holder != null) { 
        holder.pb.setVisibility(View.VISIBLE); 
       } 
      } 

      @Override 
      public void onLoadingFailed(String imageUri, View view, 
        FailReason failReason) { 
       ViewHolder holder = holderMap.get(position); 
       if (holder != null) { 
        holder.pb.setVisibility(View.GONE); 
       } 
      } 

      @Override 
      public void onLoadingComplete(String imageUri, 
              View view, Bitmap loadedImage) { 
       ViewHolder holder = holderMap.get(position); 
       if (holder != null) { 
        holder.pb.setVisibility(View.GONE); 
        wall.isDownloaded = true; 
        wallpapersList.set(position, wall); 
       } 
      } 

      @Override 
      public void onLoadingCancelled(String imageUri, View view) { 
      } 


     }, new ImageLoadingProgressListener(){ 

      @Override 
      public void onProgressUpdate(String imageUri, View view, 
        int current, int total) { 
       ViewHolder holder = holderMap.get(position); 
       if (holder != null) { 
        holder.pb.setProgress(Math.round(100.0f * current/total)); 
       } 
      } 

     }); 
    } else { 
     mImageLoader.displayImage(wall.smallURL, holder.smallThumb); 
     holder.pb.setVisibility(View.GONE); 
    } 
} 

EDIT: Пожалуйста, смотрите мой предыдущий ответ на аналогичную проблему (где я использовал разрежённый массив называется ivMap - немного лучший вариантом, чем HashMap, когда ключ является целым). Android BaseAdapter With LruCache Some ui problems

2nd EDIT: модифицированный код с адаптированным решением карты.

+0

Nope это кажется, как это работает, только если я не прокручиваюсь, когда я прокручиваю вниз, он показывает элементы заряжали, на неправильных позициях, он даже показывает ранее загруженные изображения на слотах, еще не загружены –

+0

Правильно, это звучит так, как я предупреждал, с переработанными видами. Вы посмотрели ответ в ссылке, которую я разместил? Вы можете использовать карту (называемую ivMap в моем другом ответе), поддерживать ее внутри getView и ссылаться на нее, когда заканчивается загрузчик изображений. – Bruce

+0

да, но смотрите здесь: wallpapersList.set (позиция, стена); У меня уже есть что-то подобное, он делает то же самое, это не помогает. –

Смежные вопросы