2011-08-31 42 views
0

我使用Fedors實現延遲加載圖像。但有時,listview中的第一個項目會獲得與列表中最後一個可見項目相同的圖像。所有其他項目獲得正確的圖像。如果我開始在列表中滾動,則第一個項目會更新爲正確的圖像。在我的日誌中,我可以看到ImageView具有相同的toString輸出,所以這一定是我猜的問題:Fedors Lazylist有時會顯示相同的圖像

DEBUG/ImageLoader(6168):Bitmap:[email protected] ImageView:android.widget。 ImageView的@ 463c1078

DEBUG/ImageLoader的(6168):位圖:[email protected] ImageView的:[email protected]

public class AdapterPropertyFavouritesList extends ArrayAdapter<Property> { 
    private final Activity activity; 
    private final List<Property> events; 
    public ImageLoader imageLoader; 

public AdapterPropertyFavouritesList(Activity activity, List<Property> objects) { 
    super(activity, R.layout.favourite_item , objects); 
    this.activity = activity; 
    this.events = objects; 
    App app = (App)activity.getApplication(); 
    imageLoader = app.getImageLoader(); 
} 

public static class ViewHolder{ 
    public TextView address1; 
    public TextView address2; 
    public TextView price; 
    public ImageView image; 
    public RatingBar ratingBar; 
    public View event; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View rowView = convertView; 
    ViewHolder holder; 

    if(rowView == null) 
    {  
     LayoutInflater inflater = activity.getLayoutInflater(); 
     rowView = inflater.inflate(R.layout.favourite_item, null); 
     holder = new ViewHolder(); 
     holder.address1 = (TextView)rowView.findViewById(R.id.address1); 
     holder.address2 = (TextView)rowView.findViewById(R.id.address2); 
     holder.price = (TextView)rowView.findViewById(R.id.price); 
     holder.image = (ImageView)rowView.findViewById(R.id.propertyThumbImg); 
     holder.ratingBar = (RatingBar)rowView.findViewById(R.id.ratingbar_1); 
     holder.event = (View)rowView.findViewById(R.id.event); 
    } 
    else 
    holder=(ViewHolder)rowView.getTag(); 

    final Property p = events.get(position); 
    if (p != null) 
    { 
holder.address1.setText(p.getStreetName()); 
     holder.address2.setText(p.getZipcodeCountry()); 
     holder.price.setText(ViewHelper.getFormatedMoneyValue(p.price)); 
     holder.ratingBar.setRating(p.getTotalRating()); 


     String url = p.getImage(0); 
     if(url!=null) 
     { 
      imageLoader.DisplayImage(url, activity, holder.image); 
     } 
     else 
     { 
      holder.image.setImageResource(R.drawable.no_photo_available); 
     } 
     rowView.setTag(holder); 
    } 

    if(p.hasEvents()) 
    { 
     holder.event.setVisibility(View.VISIBLE); 
    } 
    else 
    {   
     holder.event.setVisibility(View.GONE); 
    } 
    return rowView; 
}  

}

public class ImageLoader{ 
private static final String TAG = ImageLoader.class.getSimpleName(); 
private boolean scaleImage = false; 
MemoryCache memoryCache = new MemoryCache(); 
FileCache fileCache; 
private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); 

public ImageLoader(Context context) 
{ 
    // Make the background thead low priority. This way it will not affect 
    // the UI performance 
    photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1); 

    fileCache = new FileCache(context); 
} 

private final int stub_id = R.drawable.loading_1; 

public void DisplayImage(String url, Activity activity, ImageView imageView) 
{ 
    imageViews.put(imageView, url); 
    Bitmap bitmap = memoryCache.get(url); 
    if (bitmap != null) 
    { 

     imageView.setImageBitmap(bitmap); 
     if(App.LOG_ON) 
     { 
      App.log(TAG, "Bitmap: "+bitmap+" ImageView: "+imageView); 
     } 


    }   
    else 
    { 
     queuePhoto(url, activity, imageView); 
     imageView.setImageResource(stub_id); 

     if(App.LOG_ON) 
     { 
      App.log(TAG, "------------------------"); 
      App.log(TAG, "queuePhoto. Set default image on ImageView: "+imageView); 
      App.log(TAG, "queuePhoto. url: "+url); 
      App.log(TAG, "------------------------"); 
     } 

    } 
} 



public boolean hasAllImagesCached(List<String> urls) 
{ 
    boolean found = false; 
    for(int i = 0; i < urls.size() && !found; i++) 
    { 
     String url = urls.get(i); 
     if(!memoryCache.containsImage(url)) 
     { 
      found = true; 
     } 
    } 
    return !found; 
} 

private void queuePhoto(String url, Activity activity, ImageView imageView) 
{ 
    // This ImageView may be used for other images before. So there may be 
    // some old tasks in the queue. We need to discard them. 
    photosQueue.Clean(imageView); 
    PhotoToLoad p = new PhotoToLoad(url, imageView); 
    synchronized (photosQueue.photosToLoad) 
    { 
     photosQueue.photosToLoad.push(p); 
     photosQueue.photosToLoad.notifyAll(); 
    } 

    // start thread if it's not started yet 
    if (photoLoaderThread.getState() == Thread.State.NEW) 
     photoLoaderThread.start(); 
} 

private Bitmap getBitmap(String url) 
{ 
    File f = fileCache.getFile(url); 

    // from SD cache 
    Bitmap b = decodeFile(f); 
    if (b != null) 
     return b; 

    // from web 
    try 
    { 
     Bitmap bitmap = null; 
     URL imageUrl = new URL(url); 
     HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection(); 
     conn.setConnectTimeout(8000); 
     conn.setReadTimeout(8000); 
     InputStream is = conn.getInputStream(); 
     OutputStream os = new FileOutputStream(f); 
     Utils.CopyStream(is, os); 
     os.close(); 
     bitmap = decodeFile(f); 
     return bitmap; 
    } catch (Exception ex) 
    { 
     ex.printStackTrace(); 
     return null; 
    } 
} 

// decodes image and scales it to reduce memory consumption 
private Bitmap decodeFile(File f) 
{ 
    try 
    { 
     // decode image size 
     BitmapFactory.Options o = new BitmapFactory.Options(); 
     o.inJustDecodeBounds = true; 
     BitmapFactory.decodeStream(new FileInputStream(f), null, o); 

     BitmapFactory.Options o2 = null; 
     // decode with inSampleSize 
     if (scaleImage) 
     { 
      // Find the correct scale value. It should be the power of 2. 
      final int REQUIRED_SIZE = 70; 
      int width_tmp = o.outWidth, height_tmp = o.outHeight; 
      int scale = 1; 
      while (true) 
      { 
       if (width_tmp/2 < REQUIRED_SIZE || height_tmp/2 < REQUIRED_SIZE) 
        break; 
       width_tmp /= 2; 
       height_tmp /= 2; 
       scale *= 2; 
      } 
      o2 = new BitmapFactory.Options(); 
      o2.inSampleSize = scale; 
     } 

     return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); 
    } catch (FileNotFoundException e) 
    { 
    } 
    return null; 
} 

// Task for the queue 
private class PhotoToLoad 
{ 
    public String url; 
    public ImageView imageView; 

    public PhotoToLoad(String u, ImageView i) 
    { 
     url = u; 
     imageView = i; 
    } 
} 

PhotosQueue photosQueue = new PhotosQueue(); 

public void stopThread() 
{ 
    photoLoaderThread.interrupt(); 
} 

// stores list of photos to download 
class PhotosQueue 
{ 
    private Stack<PhotoToLoad> photosToLoad = new Stack<PhotoToLoad>(); 

    // removes all instances of this ImageView 
    public void Clean(ImageView image) 
    { 
     for (int j = 0; j < photosToLoad.size();) 
     { 
      if (photosToLoad.get(j).imageView == image) 
      { 
       photosToLoad.remove(j); 
       if(App.LOG_ON) 
       { 
        App.log(TAG, "photo removed"); 
       } 
      }    
      else 
      { 
       ++j; 
      } 

     } 
    } 
} 

class PhotosLoader extends Thread 
{ 
    public void run() 
    { 
     try 
     { 
      while (true) 
      { 
       // thread waits until there are any images to load in the 
       // queue 
       if (photosQueue.photosToLoad.size() == 0) 
        synchronized (photosQueue.photosToLoad) 
        { 
         photosQueue.photosToLoad.wait(); 
        } 
       if (photosQueue.photosToLoad.size() != 0) 
       { 
        PhotoToLoad photoToLoad; 
        synchronized (photosQueue.photosToLoad) 
        { 
         photoToLoad = photosQueue.photosToLoad.pop(); 
        } 
        Bitmap bmp = getBitmap(photoToLoad.url); 
        memoryCache.put(photoToLoad.url, bmp); 
        String tag = imageViews.get(photoToLoad.imageView); 
        if (tag != null && tag.equals(photoToLoad.url)) 
        { 
         BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad.imageView); 
         Activity a = (Activity) photoToLoad.imageView.getContext(); 
         a.runOnUiThread(bd); 
        } 
       } 
       if (Thread.interrupted()) 
        break; 
      } 
     } catch (InterruptedException e) 
     { 
      // allow thread to exit 
     } 
    } 
} 

PhotosLoader photoLoaderThread = new PhotosLoader(); 

// Used to display bitmap in the UI thread 
class BitmapDisplayer implements Runnable 
{ 
    Bitmap bitmap; 
    ImageView imageView; 

    public BitmapDisplayer(Bitmap b, ImageView i) 
    { 
     bitmap = b; 
     imageView = i; 
    } 

    public void run() 
    { 
     if (bitmap != null) 
      imageView.setImageBitmap(bitmap); 
     else 
      imageView.setImageResource(stub_id); 
    } 
} 

public void clearCache() 
{ 
    memoryCache.clear(); 
    fileCache.clear(); 
} 

public synchronized boolean isScaleImage() 
{ 
    return scaleImage; 
} 

public synchronized void setScaleImage(boolean scaleImage) 
{ 
    this.scaleImage = scaleImage; 
} 

}

回答

0

問題似乎已解決。我的listview被放置在一個自定義對話框中。 getview方法被調用了6次,即使列表中只有2個項目。我將高度參數從「wrap_content」更改爲80 *(listitems.size()),問題解決了。

0

我的一個應用程序有很多圖片,但是我用畫廊而不是這種方法來查看它們。然而,我在一些圖片上遇到了很奇怪的問題。我看着那些比其他人大得多的圖像。我會說看看你的照片,如果其他人比其他人大,然後看看這些對應的列表中的項目變得腐敗。如果有些更大尺寸調整它們並查看問題是否仍然存在

+0

所有圖像都有相同的圖像大小400x300。 –

0

其實這裏是一個惰性加載圖像實現的鏈接,我認爲它比Fedor更好:Image Download。也許它可以幫助你。

+0

可疑鏈接? :f –

+0

Ops,抱歉,我上傳了Google顯示給我的第一個網站中的zip文件,幾秒鐘後我會用另一個鏈接更新我的答案。 –

+0

答案已更新。 –