ListView中的图片加载哪种方法更好?

9

我想知道在从Web加载ListView中的图像时,哪种方法更好,是通过同时运行一些线程批量加载还是一个接一个地通过线程队列加载?

我注意到(但我不知道是否真正实现了这一点),YouTube应用程序通过批处理加载图像,速度很快。甚至不仅加载图像,还从Web请求一些数据。有人有想法吗?

4个回答

6
“更好”是以哪种方式为基准?性能方面?开发友好度?易用性方面?
需要考虑的一些基本事项:
1. 创建线程是昂贵的。它很慢,每个线程都会消耗系统资源(当然)。当为每个下载创建单个线程时,请使用受管理的有界线程池。
2. 如果图片对用户不可见,则不要加载它们。你应该在你的ListAdapter的getView()中检查图像是否已经被加载,如果没有,则重用线程池中的一个线程来完成工作。
3. 谨慎使用AsyncTask。据我所知,AsyncTask管理一个固定的、应用程序范围内的线程池(我认为它限制为5个线程),因此如果所有这些线程都忙于加载图像,则通过该类执行的任何其他任务都将被阻塞。
4. 不要重新发明轮子。ImageLoader of Droid-Fu 是否解决了你的问题?它还实现了缓存,因此不会重复下载图片。

ImageLoader在ListView中最初加载的图像位置不正确,但过一段时间后它会刷新,然后图像就会出现在正确的位置。我只是将这行代码放入了我的listview适配器的getView()方法中:ImageLoader.start(imageUrl, new ImageLoaderHandler(imageView)); 我该如何纠正这个问题?你能帮忙吗? - capecrawler
更新-我设法通过在ListView的每个视图中设置标签来修复它,当图像准备好时,我通过与图像关联的标签找到该视图,并使用该图像设置ImageView。你的ImageLoader很棒...非常感谢。 - capecrawler
是的,在重复使用视图和并发时,必须小心,因为在将新图像发送回视图之前,视图所有者可能会更改。使用视图标记是处理此问题的非常好的解决方案。另外,如果这个回答解决了你的问题,请将其标记为解决方案 :-) - mxk
4
顺便说一下,我有时会收到警告: 02-15 13:02:27.839: WARN/nalizableReferenceQueue(1490): Could not load Finalizer in its own class loader. Loading Finalizer in the current class loader instead. As a result, you will not be able to garbage collect this class loader. To support reclaiming this class loader, either resolve the underlying issue, or move Google Collections to your system class path. 我该如何解决这个问题? - capecrawler
这是因为缓存是使用MapMaker实现的,但我没有将整个Guava库与Droid-Fu捆绑在一起。这是在ProGuard集成到Android工具链之前完成的,我不想强制Droid-Fu用户安装一兆字节的库依赖项,以使缓存正常工作。 - mxk

1

实现此类功能的最佳方法是在列表中使用“懒加载”图像。如果您的列表大小固定,则运行多个线程(每个可见列表项一个),下载图像并刷新列表中的图像。在此期间,在相同位置放置一些虚拟图像。

仅为您的列表提供固定数量的图像组件,最好比任何时候可见图像的总数多几个。每次滚动列表时,检查是否存在与该特定列表项对应的图像。如果是,则显示。如果没有,则显示虚拟图像,运行线程以在后台加载图像,并在下载完成后刷新列表图像。

为了进一步节省内存,您可以为图像组件使用“软引用”。这允许垃圾收集器取走当前未显示在屏幕上的图像。


1

1

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