Fedors Lazylist иногда показывает одно и то же изображение - PullRequest
0 голосов
/ 31 августа 2011

Я использую реализацию Fedors для отложенной загрузки изображений. Но иногда первый элемент в представлении списка получает то же изображение, что и последний видимый элемент в списке. Все остальные предметы получают правильное изображение. Если я начну прокручивать свой список, то первый элемент будет обновлен с правильным изображением. В моем журнале я вижу, что ImageView имеет тот же вывод toString, поэтому я думаю, что это проблема:

DEBUG / ImageLoader (6168): растровое изображение: android.graphics.Bitmap@46363010 ImageView: android.widget.ImageView@463c1078

DEBUG / ImageLoader (6168): растровое изображение: 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.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;
}

}

Ответы [ 3 ]

0 голосов
/ 01 сентября 2011

Кажется, проблема решена.Мой список был помещен в пользовательский диалог.Метод getview вызывался 6 раз, хотя в списке было только 2 элемента.Я изменил параметр высоты с "wrap_content" на 80 * (listitems.size ()), и проблема была решена.

0 голосов
/ 20 сентября 2011

На самом деле вот ссылка на реализацию отложенной загрузки изображений, которая, я думаю, лучше, чем у Федора: Загрузка изображений . Может быть, она может вам помочь.

0 голосов
/ 31 августа 2011

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

...