Android 安卓画廊视图“;口吃“;使用延迟映像加载适配器
我想创建一个延迟加载适配器,用于Android 安卓画廊视图“;口吃“;使用延迟映像加载适配器,android,android-gallery,android-adapter,Android,Android Gallery,Android Adapter,我想创建一个延迟加载适配器,用于Gallery小部件 也就是说,getView()立即返回一个ImageView,稍后其他一些机制将异步调用它的setImageBitmap()方法。为此,我创建了一个“懒惰的”ImageView,它扩展了ImageView public class GalleryImageView extends ImageView { // ... other stuff here ... public void setImage(final Looper
Gallery
小部件
也就是说,getView()
立即返回一个ImageView
,稍后其他一些机制将异步调用它的setImageBitmap()
方法。为此,我创建了一个“懒惰的”ImageView
,它扩展了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的onLayout方法中的一个bug。查看可能的解决方法 解决方案是实现一种更智能的方法来确定何时获取缩略图-在用户浏览列表时获取缩略图是毫无意义的。实际上,您希望在Romain Guy的应用程序中实现类似的功能
要获得响应速度最快的多媒体资料,您需要实现某种形式的内存缓存,并执行以下操作:
- 仅当图像存在于
getView
的内存缓存中时才设置图像。设置一个标志,指示是否已设置映像或是否需要下载。您还可以在SD卡的缓存和内部内存中保留一个内存,如果当前未进行放纵,则显示一个低分辨率(inSampleSize
设置为16或8)版本,仅在滚动浏览时即可看到该版本-当用户放开并固定在图像上时,将加载高分辨率版本
- 添加一个
OnItemSelectedListener
(并确保在初始化时调用setCallbackDuringFling(false)
),为所有需要下载的可见项目下载新的缩略图(仅当用户竖起手指时)(您可以使用getFirstVisiblePosition
和getLastVisiblePosition
查找可见视图的范围)
- 此外,当用户抬起手指时,检查1.如果用户放下手指后所选位置发生了变化,如果发生了变化2.下载是否是由于您的
OnItemSelectedListener启动的
-如果不是,则启动一个。这是为了捕捉不发生投掷的情况,从而OnItemSelected
never会做任何事情,因为在这种情况下它总是在手指向下的情况下被调用。我会使用一个处理程序来延迟在库的动画时间开始下载(确保在调用onItemSelected
时或当您得到一个ACTION\u down
事件时清除任何延迟发送到该处理程序的消息
- 下载图像后,检查是否有任何可见视图请求此图像,然后更新这些视图
还要注意,默认的Gallery组件没有正确地实现视图回收(它假定适配器中的每个位置都有一个唯一的视图,并且在这些项目离开屏幕时清除回收器,使其变得毫无意义).Edit:对于更多视图,它并不是毫无意义的-但它不是下一个/上一个视图的回收器,而是为了避免在布局更改期间必须为当前视图调用getView
这意味着传递给getView
方法的convertView
参数通常不为空,这意味着您将增加很多视图(这是非常昂贵的)-请参阅我对的回答,以获取有关这方面的一些提示。(PS:我已经修改了该代码-我将在布局阶段的位置为布局阶段和滚动阶段使用不同的回收站,并根据它们的位置检索布局回收站中的视图,如果从该回收站获得的视图不为空,则不调用getView,因为它将是完全相同的视图;此外,请重新清除布局在布局阶段之后循环垃圾箱--这会使事情变得更加快速)
PS:在OnItemSelected
中的操作也要非常小心-也就是说,除非它位于上述位置,否则请尽量少做。例如,我在OnItemSelected
中我的图库上方的TextView
中设置了一些文本。只需将此调用移动到与我更新缩略图的位置相同的位置这是一个明显的不同。我有一个答案给你
当在内部的ImageView
上调用任何setImage…
方法时,将请求布局过程,例如,如上定义的setImageBitmap()
public void setImageBitmap(Bitmap bm) {
setImageDrawable(new BitmapDrawable(mContext.getResources(), bm));
}
哪个叫
public void setImageDrawable(Drawable drawable) {
if (mDrawable != drawable) {
mResource = 0;
mUri = null;
updateDrawable(drawable);
requestLayout(); //layout requested here!
invalidate();
}
}
它的效果是将库“捕捉”到当前最靠近库中心的图像中心
我所做的防止这种情况的措施是让加载到库中的视图具有明确的高度和宽度(在dip
s中)使用一个忽略布局请求的ImageView
子类。这样做的原因是画廊最初仍然有一个布局过程,但不会在画廊中的图像每次更改时都这样做,我想只有当画廊视图的宽度和高度设置为WRAP\u CONTENT
时才会发生这种情况,而我们没有这样做。请注意,由于在setImageDrawable()
中仍调用了invalidate()
,因此在设置时仍将绘制图像
下面是我非常简单的ImageView
子类
/**
* This class is useful when loading images (say via a url or file cache) into
* ImageView that are contained in dynamic views (Gallerys and ListViews for
* example) The width and height should be set explicitly instead of using
* wrap_content as any wrapping of content will not be triggered by the image
* drawable or bitmap being set (which is normal behaviour for an ImageView)
*
*/
public class ImageViewNoLayoutRefresh extends ImageView
{
public ImageViewNoLayoutRefresh(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public ImageViewNoLayoutRefresh(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ImageViewNoLayoutRefresh(Context context)
{
super(context);
}
@Override
public void requestLayout()
{
// do nothing - for this to work well this image view should have its dims
// set explicitly
}
}
编辑:我应该提到的是,我选择的方法也可以起作用,但由于我需要在抛投过程中融入其中,所以我提出了上面的方法,我认为这是一种更灵活的方法我也有同样的问题。滚动是粘性的,在回到原来的位置之前,整个过程有点左右摇摆。您是否找到了解决方案?您使用的是哪一版本的Android?当您不使用自定义ImageView时是否会出现此问题?问题是否已解决