Android ListView 预加载数据行

3
我在我的应用程序中有一个Android ListView,并在每行中显示不同的图像(每行1个图像,高度不确定)。这些图像使用AsyncTask从网络加载,否则它会从缓存中获取,所以一切都很好。
过程是,在我的适配器的每个getView中(除非在缓存中找到)我都有一个指向图像的url,我启动一个异步任务来设置我的ImageView。我给它一个定义的宽度,以适应屏幕(然后我使用这个定义的宽度来缩放高度,所以我知道宽度但在下载和设置之前不知道高度(或图像的纵横比))
向下滚动时一切正常,因为List View预加载了大约5行..它会在我的代码中触发5次调用以下载图像。这使得向下滚动平稳。
问题在于当我向上滚动时。当我向上滚动时,视图被重用,我知道一个宽度,所以没问题,但最初高度为0,直到我完全加载图像;当它完全加载时,Image View会扩展到任何高度(即1024),这会使滚动变得不流畅,因为它将视图从0扩展到1024并将焦点带回该视图的顶部...
问题:是否可能将List View设置为预加载向下和向上到一定大小..?因此,向上滚动时,我的ListView已准备好显示5行。我知道这在android.support.v4.view.ViewPager中是可能的(默认情况下它预加载+1和-1..但可以更改为+5和-5)。

你在使用什么适配器?在其中,你是否使用了bindView? - Budimir Grom
我正在使用BaseAdapter... 只是使用getView方法,填充我的布局之一,将视图设置为我想要的任何内容并返回它。 - vankizer
我有一种解决方案...当我下载新图像时,我记录高度并将其放入HashMap中,稍后检查是否缓存了该图像。如果是,则知道它的高度,然后设置imageView对象的宽度和高度,这样它就不会跳来跳去了..但是在重建Fragments/Activities生命周期期间处理这个可能会麻烦...不确定如何解决。 - vankizer
我刚刚发现了这篇关于RecyclerView博客文章。(a)无论如何,这可能对你有兴趣,(b)它提到了处理类似用例的ViewHolder模式。 - Jan Groth
使用ListView时,您为每一行调用asynctask。因此,当您随机向上或向下滚动时,每一行只会调用1个asynchtask吗? - Manmohan Badaya
是的,我的ListView的每一行都包含几个按钮、ImageView和一些TextView。当我滚动时,它会设置文本(从ArrayList中,根据位置)并将图像URL设置为ImageView(如果尚未缓存),然后执行异步任务来获取它。所以是的,每行一个。 - vankizer
1个回答

0

我认为你应该在继承了BaseAdapter的适配器中重写newView而不是getView。别忘了调用super.newView

原因是为了避免在向上滚动时绑定视图(行)。方法newView对于每一行只会被调用一次。而getView也会绑定视图,这会导致图片重新加载,当你向上滚动时。如果我没记错的话,我认为这就是问题所在。

当然,这只有在图片加载后不再改变的情况下才有意义。如果图片在向上和向下滚动时需要动态更改,那么我想你就无能为力了,但我怀疑这种情况并不常见。我想你不会保存旧/废弃图像的高度。


另外,你可以将高度作为数据加载到你的AsyncTask中,从服务器获取一个数字。这样会更快。 - Budimir Grom
没错,它们不会。我按特定顺序提取URL数组并显示它们,有时刷新后顺序可能会改变,但这就是为什么我将URL哈希到高度而不是位置到高度。 - vankizer
我看了一下newView方法,它没有位置信息?我正在使用它和ArrayList来访问所有的数据... 我只用了getView,所以可能有些东西我没注意到。 - vankizer
好的,如果位置改变,我不知道该怎么办。也许快速将高度/网址作为数据/数字加载? - Budimir Grom
我想我会调整我的数据库来保存宽度和高度,并在获取其余信息的请求中获取该信息,并在尝试下载之前设置imageView。 非常感谢。 - vankizer
@vankizer:不用谢。我希望有人能给你一个更好的答案。我没有看到其他不需要更多工作的方法。 - Budimir Grom

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