Android Gallery View 和适配器 getView 被多次调用
我有一个画廊,它有一个适配器连接到它。在 getView 方法中,我有一个自定义布局,这样我就可以将图像和标题显示在一起。
图像是从 URL 下载的,这是异步完成的,并且按预期工作。
目前我使每个项目都填满屏幕,所以我一次只显示一个项目,基本上我想让它像幻灯片放映一样。
让我说清楚,目前我有一个活动,它只有一个视图,即画廊。
当我滑动时出现问题,图像弹起并保持在同一图像。我需要多次用力、长时间地滑动,然后才能到达下一张图像。
我在 getView() 的自定义适配器中添加了一条调试消息,似乎 getView 被调用了很多次(4 次),并且传递的位置要么是当前位置,要么是上一个位置,这解释了为什么我被困在同一屏幕。
如果我删除远程下载图像部分,或者只是使用手机中的静态图像,我就不会再遇到任何问题,事实上, getView 仅被调用一次,并且位置正确。
我很沮丧,不知道问题是什么,可能是因为我正在异步下载图像,这会导致图像更新,从而导致 getView 再次被调用以重绘自身? 我不确定..
请帮忙
I have a Gallery, which has an adapter connects to it. In the getView method, i have a custom layout, so that I can i have image and caption displayed together
The image is downloaded from an URL, which is done asynchously, and working as expected.
Currently i make each item to fill the screen, so i only have one item display at a time, basically i want to make it like a slide show.
let me be clear, currently i have an activity, and it only has one View, which is a Gallery.
problem occurs when I am swiping, the image bounces and stays at the same image. i need to swipe many times, hard, and long swipe, then i can get to next image.
i put a debug message in my custom adapter in the getView(), it seems getView is getting called many times (4 times), and position being passed is either the current position or the previous one, which explains why i am stuck at the same screen.
if i remove the remote downloading image part, or just use a static image form the phone, i don't have any more issues, in fact, the getView only gets called once, with correct position.
i am very frustrated, not sure what the problem is, could it be because i am downloading image asynchously, which will cause the image to update which causes getView to get called again to redraw itself?
i am not sure..
please help
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不幸的是,这是画廊的一个错误。无论数据是否异步更新,列表视图都会很好地滚动。但是,图库的编码不符合列表视图的标准,
当图库尝试更新可见视图(由于图像加载回调)时,该视图将“捕捉”回焦点位置。如果您在滚动时以任何方式更改视图,它就会捕捉。这可能就是为什么您必须用力滚动才能离开当前视图的原因。它试图在您的视图上执行回调,只有快速滚动才能防止在您离开该视图之前发生回调。
我不久前在这里报告了这个错误:
Android 问题
如果您打算使用图库,则可以尝试其中发布的一些解决方法。
不幸的是它还没有引起Android开发者的注意。
看来问题是由于视图设置为“wrap_content”并且画廊必须重新测量/重绘其视图
而引起的,此后我不再使用画廊而是使用 ViewPager。管理起来就容易多了,不用担心这个问题。自首次引入画廊以来,这一直是画廊的一个已知问题。我不知道这个问题是否在任何较新的 Android 版本(3.x/4.x)中得到修复。从 2.3.7 开始,它尚未修复。
Unfortunately this is a bug with gallery. Listviews will scroll nicely regardless of data being updated asynchronously. However, the gallery is just not coded up to par with the listview
When the gallery tries to update a visible view (due to your image loading callback) this view will "snap" back to the focused position. If you are changing the view in any way when it is scrolling it will snap. This is likely why you have to scroll hard to get away from the current view. It is trying to perform a callback on your view and only scrolling fast will prevent the callback from occurring before you move away from that view.
I've reported this bug a while ago here:
Android Issues
There are a few workarounds posted in there you can try if you are set on using a Gallery.
Unfortunately it hasn't gained attention from the Android developers.
It seems the issue is caused with views being set to "wrap_content" and the gallery having to remeasure/redraw its views
I have since migrated away from using the gallery and instead use a ViewPager. It is much easier to manage and you don't have to worry about this problem. This has been a known problem with the Gallery since the gallery was first introduced. I have no idea if this was fixed in any of the newer Android versions (3.x/4.x). As of 2.3.7 it is not fixed.
首先您应该注意:任何 AdapterView(Gallery、ListView 等)都不保证每次调用 getView() 方法时都会传递相同的 View 实例参数。它仅保证每个视图具有相同的类型(请参阅 Adapter.getIntemViewType() 方法文档)
因此,当您开始下载图像时,您应该只指定元素的位置。下载图像后,您应该在 Adapter.getView() 方法调用中将指定的 ImageView 与下载的图像绑定。
在此处查看 Android 示例中的 ImageDownloader
另一种方法是使用 WeakHashMap 来包含适配器视图到其位置的映射。如果您需要,我可以为您提供代码示例。
At first you should note: Any AdapterView (Gallery, ListView etc) doesn't guarantee that each time getView() method is called it will pass the same View instance parameter. It only guarantees that each view will have the same type (see Adapter.getIntemViewType() method docs)
So, when you start image downloading you should only specify position of the element. Then after the image has been downloaded you should bind specified ImageView with downloaded image in Adapter.getView() method call.
Take a look to the ImageDownloader from the Android samples here
The other approach is to use WeakHashMap in order to contain map of adapter views to its positions. I can provide you with code samples if you need.