开发者

Fedors Lazylist sometimes showing the same image

I am using Fedors implementation of lazy loading images. But sometimes the first item in the listview gets the same image as the last visible item in the list. All other items gets the correct image. If I start scrolling in my list, then the first item gets updated with the correct image. In my log i can see that the ImageView has the same toString output, so that must be the problem I guess:

DEBUG/ImageLoader(6168): Bitmap: android.graphics.Bitmap@46363010 ImageView: android.widget.ImageView@463c1078

DEBUG/ImageLoader(6168): Bitmap: android.graphics.Bitmap@463be868 ImageView: android.widget.ImageView@463c1078

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.addr开发者_C百科ess2.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;
}

}


one of my apps had alot of pictures, however i used the gallery as opposed to this method for viewing them. however i had very strange issues on some pictures. i looked and those images where much larger then the rest. i would say to take a look at your pictures and if some are larger then the rest and see if those correspond to the items in the list getting corrupt. if some are larger resize them down and see if the problem still happens


Actually here is a link of an Lazy Loading image implementation which I think it's better than Fedor's : Image Download.Maybe it can help you.


The problem seems to be solved. My listview was placed in a custom dialog. The getview method was called 6 times, even though that there were only 2 items in the list. I changed the height parameter from "wrap_content" to 80*(listitems.size()) and the problem was solved.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜