Android-Universal-Image-Loader在GridView滚动时不会保留已加载的图片

8
我正在使用Android-Universal-Image-Loader库,在我的GridView单元格中加载远程图片到ImageView中。
以下是imageLoader的配置:
new ImageLoaderConfiguration.Builder(Config.context)
.threadPriority(Thread.NORM_PRIORITY - 2)
.memoryCacheSize(20 * 1024 * 1024) // 20 Mb
.memoryCache(new LruMemoryCache(20 * 1024 * 1024))
.defaultDisplayImageOptions(DisplayImageOptions.createSimple())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.enableLogging() // Not necessary in common
.build();

和显示选项:

new DisplayImageOptions.Builder()
.showStubImage(R.drawable.blank)
.showImageForEmptyUri(R.drawable.no_image)
.build();

问题: 一旦启动带有网格视图的活动,所有内容正常工作并且图像出现在单元格中, 然后我向下滚动网格(我有大约20个项目在网格中),其他图像会正确加载。 但是一旦我向上滚动,已经加载的图像开始重新加载。
几次上下滚动后,网格保存了所有图像,它们不再消失。
有人遇到过类似的问题或者你知道我做错了什么。感谢您的帮助。
添加: 这是我的适配器中的getView方法:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    View view = convertView;
    ViewHolder holder;

    if ( view == null ) {           
        view = Config.context.getLayoutInflater().inflate(R.layout.featured, null);
        holder = new ViewHolder();

        holder.titleText = (TextView) view.findViewById(R.id.featured_title);
        holder.priceText = (TextView) view.findViewById(R.id.featured_price);
        holder.image = (ImageView) view.findViewById(R.id.thumbnail_image);

        view.setTag(holder);
    }
    else {
        holder = (ViewHolder) view.getTag();
    }

    HashMap<String, String> listing = listings.get(position);

    /* set text values */
    holder.titleText.setText(listing.get("title"));
    holder.priceText.setText(listing.get("price"));

    /* load image to list (AsyncTask) */
    Utils.imageLoaderFeatured.displayImage(listing.get("photo"), holder.image, Utils.imageLoaderOptionsFeatured);

    return view;
}

附注:如果您想查看其他代码(可能是网格适配器),以帮助我解决此问题,请告诉我。

约翰


1
我看到你没有使用内存或磁盘缓存。尝试在显示选项中启用缓存。 - nostra13
我之前使用过它,但在更新库到1.8.5版本后将其删除,因为.cacheInMemory()和.cacheOnDisc()已被弃用,即使使用.cacheInMemory(),图片也无法从第一次开始保留,用户必须上下滚动至少4次才能使应用程序缓存网格中的所有图片。 - John F
你应该阅读那些被弃用的方法的Java文档。这样你就可以看到你应该使用.cacheInMemory(true).cacheOnDisc(true)代替它们。你在UIL示例应用程序中看到了你的问题吗? - nostra13
嗨NOSTRA,感谢您对弃用问题的澄清,我已经理解并进行了更正,但问题仍然存在,并且在UIL示例应用程序中的网格中表现相同。我在三星Galaxy Nexus和三星N800平板电脑上进行了测试,只有在GRID视图中,列表视图才能正确保存图片。如果您想要,我可以尝试录制视频。 - John F
嗨Nostra,库中的问题仍然存在,请检查一下... - John F
显示剩余2条评论
6个回答

16

我在Universal-Image-Loader Demo上遇到了同样的问题,希望库的开发人员能在下一个更新中解决这个问题。

更新: 在 1.9版本 的帮助下,问题已经得到解决,您需要更新库并使用以下方法在imageView中显示图片:

ImageAware imageAware = new ImageViewAware(imageView, false);
imageLoader.displayImage(imageUri, imageAware);

它解决了我的问题。关于为什么你应该这样做的一些细节可以在这里这里找到。


我尝试过这个方法 - 但它创建了一个问题,即在应该加载占位符图片的地方显示已经加载的图片,而在一段时间后才会加载正确的图片。 - Narendra Singh

1
在适配器的getView()方法中不要使用set标签,始终尝试在适配器的getview()方法中查找视图ID。
public View getView(final int position, View convertView, ViewGroup parent) {

View view = convertView;
ViewHolder holder;


    view = Config.context.getLayoutInflater().inflate(R.layout.featured, null);
    holder = new ViewHolder();

    holder.titleText = (TextView) view.findViewById(R.id.featured_title);
    holder.priceText = (TextView) view.findViewById(R.id.featured_price);
    holder.image = (ImageView) view.findViewById(R.id.thumbnail_image);

    view.setTag(holder);



HashMap<String, String> listing = listings.get(position);

/* set text values */
holder.titleText.setText(listing.get("title"));
holder.priceText.setText(listing.get("price"));

/* load image to list (AsyncTask) */
Utils.imageLoaderFeatured.displayImage(listing.get("photo"), holder.image, Utils.imageLoaderOptionsFeatured);

return view;}

这对我来说看起来是一个好答案,但请不要特别要求点赞 - 如果你创造了好的内容,它们会随着时间而来。 - halfer

1
你应该只在构造函数中声明一次ImageLoader和DisplayImageOptions实例。
ImageLoader imageLoader = ImageLoader.getInstance();
DisplayImageOptions options = new DisplayImageOptions.Builder().cacheInMemory(true)
        .cacheOnDisc(true).resetViewBeforeLoading(true)
        .showImageForEmptyUri(fallbackImage)
        .showImageOnFail(fallbackImage)
        .showImageOnLoading(fallbackImage).build();

1

您必须使用适配器,然后实现ViewHolder以使滚动流畅有效。根据在getView()中提供的位置为图像提供标记,那么就不会有问题了。


嗨Anchit,谢谢你的回答,但我正在使用viewHolder并按照你描述的一切操作。我已经将getView方法添加到帖子中,请看一下可以吗? - John F

0

我也遇到了同样的问题,使用了StaggeredGridView。即使使用了内存缓存和ImageAware方法,问题仍未解决。

唯一有效的方法是将缓存内存从4MB扩展到10MB。列表图片很小,但视图的头部有一张非常大的图片。

我注意到即使在长按时,ImageViews也会被刷新,这对于GridView是否有效呢?

无论如何,扩展内存缓存限制也解决了这个问题。


-1

我也遇到了同样的问题,并通过编写以下代码解决了问题:

Utils.imageLoaderFeatured.displayImage(listing.get("photo"), holder.image, Utils.imageLoaderOptionsFeatured);.......

在if(view==null)的代码块中添加上述代码,即只有当convert view==null时才加载和显示图片,这将解决您的问题。


1
谢谢伙计,我已经尝试过这种方法了,但在这种情况下,图像总是会改变,也就是说,每次滚动网格时它们都会混合。 - John F

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接