android画廊视图“口吃"带有延迟图像加载适配器 [英] android gallery view "stutters" with deferred image loading adapter

查看:31
本文介绍了android画廊视图“口吃"带有延迟图像加载适配器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个延迟加载适配器以与 Gallery 小部件一起使用.

I would like to create an deferred loading adapter for use with a Gallery widget.

也就是说getView()立即返回一个ImageView,稍后其他的一些机制会异步调用它的setImageBitmap()方法.我通过创建一个扩展 ImageView 的惰性"ImageView 来做到这一点.

That is to say getView() returns an ImageView immediately, and later some other mechanism will asynchronously call its setImageBitmap() method. I did this by creating a "lazy" ImageView that extends ImageView.

public class GalleryImageView extends ImageView {

    // ... other stuff here ...

    public void setImage(final Looper looper, final int position) {

    final Uri uri = looper.get(position);
    final String path = looper.sharePath(position);

    new Thread(new Runnable() {

        @Override
        public void run() {
            GalleryBitmap gbmp = new GalleryBitmap(context, uri, path);
            final Bitmap bmp = gbmp.getBitmap(); // all the work is here
            handler.post(new Runnable() {

                @Override
                public void run() {
                    if (GalleryImageView.this.getTag().equals(uri)) {
                        setImageBitmap(bmp);
                    }
                }
            });
        }
    }).start();
}

}

当我在 Gallery 中缓慢滚动时,中心图像不断弹出到中心.确切地说,这很难解释,但这真的很烦人.我也为微调适配器尝试了相同的方法,它在那里完美运行.

When I scroll slowly in the Gallery, the center image keeps popping into the center. It's hard to explain, exactly, but it's really annoying. I also tried the same approach for a spinner adapter and it works perfectly there.

有什么想法吗?

推荐答案

解决方案是实现一种更智能的方法来确定何时获取缩略图 - 在用户浏览列表时获取缩略图毫无意义.本质上,您希望在 Romain Guy 的 Shelves 应用程序中实现类似的功能.

The solution is to implement a more intelligent method of when to fetch thumbnails - it is pointless fetching thumbnails while the user is flinging through the list. Essentially you want something like that implemented in Romain Guy's Shelves application.

要获得响应速度最快的图库,您需要实现某种形式的内存缓存并执行以下操作:

To get the most responsive Gallery you'll need to implement some form of in-memory cache and do the following:

  • 仅当图像存在于您的 getView 的内存缓存中时才设置该图像.设置一个标志,指示是否设置了图像或是否需要下载.您还可以在 SD 卡和内部存储器上的缓存中维护一个内存,如果当前未进行投掷,则显示低分辨率(inSampleSize 设置为 16 或 8)版本,该版本将可见当只是滚动时 - 当用户放手并固定在图像上时,将加载高分辨率版本.
  • 添加一个 OnItemSelectedListener(并确保在初始化时调用 setCallbackDuringFling(false))为所有需要下载的可见项目下载新的缩略图如果用户手指向上(您可以使用 getFirstVisiblePositiongetLastVisiblePosition 来查找可见的视图范围)
  • 此外,当用户抬起手指时,请检查 1. 自用户放下手指后所选位置是否发生变化,如果发生变化 2. 是否由于您的 OnItemSelectedListener 启动了下载 - 如果它不是然后启动一个.这是为了捕捉没有发生投掷的情况,因此 OnItemSelected 永远不会做任何事情,因为在这种情况下它总是在手指向下的情况下被调用.我会使用一个处理程序来延迟你画廊的动画时间开始下载(确保在调用 onItemSelected 或当你收到 ACTION_DOWN 事件.
  • 下载图像后,检查是否有任何可见视图请求此图像,然后更新这些视图
  • Only set an image if it exists in the in-memory cache from your getView. Set a flag indicating whether the image was set or whether a download is required. You could also maintain a memory in a cache on the SD card and internal memory, and if a fling is not currently ongoing then show a low res (inSampleSize set to 16 or 8) version which will be visible when just scrolling through - the high res version will load when the user lets go and settles on an image.
  • Add an OnItemSelectedListener (and make sure to call setCallbackDuringFling(false) when initializing) that downloads new thumbnails for all the visible items that require a download only if the users finger is up (you can use getFirstVisiblePosition and getLastVisiblePosition to find the range of views visible)
  • Also when the user lifts their finger check to see 1. if the selected position changed since the user put their finger down and if so 2. whether a download was initiated due to your OnItemSelectedListener - if it wasn't then initiate one. This is to catch the case where no flinging occurs, and thus OnItemSelected never does anything because it is always called with the finger down in this situation. I'd use a Handler to delay starting the downloading by the animation time of your gallery (make sure to clear any delayed messages posted to this handler whenever onItemSelected is called or when you get an ACTION_DOWN event.
  • After an image is downloaded check if any visible views requested this image then and update those views

还要注意,默认的 Gallery 组件没有正确实现视图回收(它假设适配器中的每个位置都有一个独特的视图,并且在这些项目离开屏幕时清除这些项目的回收器,使其变得毫无意义).从更多的角度来看它并不是毫无意义的 - 但它不是下一个/上一个视图的回收器,而是用来避免必须为当前调用 getView布局更改期间的视图.

Also be aware that the default Gallery component does not properly implement View recycling (it assumes each position in the adapter has a unique view, and also clears the recycler of these items when they go offscreen making it pretty pointless). on more looking it isn't pointless - but it's not a recycler in terms of next/previous views, rather it serves to avoid having to call getView for the current views during layout changes.

这意味着传递给您的 getView 方法的 convertView 参数通常不会为 null,这意味着您将膨胀很多视图(这很昂贵)- 请参阅我对 是否替代图库的回答与视图回收存在? 一些提示.(PS:我已经修改了该代码 - 我将在布局阶段使用不同的回收站用于布局阶段和滚动阶段,并根据它们的位置检索布局回收站中的视图,如果您从垃圾箱中获得的视图是非空的,因为它将是完全相同的视图;还要在布局阶段之后清除布局回收站——这让事情变得更加快捷)

This means the convertView parameter passed to your getView method will more often that not be null, meaning you'll be inflating a lot of views (which is expensive) - see my answer to Does a replacement for Gallery with View recycling exist? for some hints on that. (PS: I have since modified that code - I would use a different recycle bin for layout phases and scroll phases, in the layout phase place and retrieve the views in the layout recycle bin according to their position, and DO NOT call getView if the view you get from the bin is non-null since it will be exactly the same view; also clear the layout recycle bin after the layout phase -- this makes things a bit more snappier)

PS:在OnItemSelected 中做的事情也要非常小心——也就是说,除非它在上面提到的地方,否则尽量少做.例如,我在 OnItemSelected 中的 Gallery 上方的 TextView 中设置了一些文本.将这个调用移动到与我更新缩略图相同的点上,就会产生显着的差异.

PS: Also be very careful with what you do in OnItemSelected - namely unless it's in the places mentioned above then try to do as little as possible. For instance I was setting some text in a TextView above my Gallery in OnItemSelected. Just moving this call into the same points as where I updated thumbnails made a noticable difference.

这篇关于android画廊视图“口吃"带有延迟图像加载适配器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆