我有GridView,其中从服务器下载图像,我使用延迟加载方法将图像异步添加到网格。
我可以看到多次调用getView方法并且对于网格视图的位置不一致,直到图像被下载到位置。
现在,当我滚动gridview时,已经下载到位置的图像现在被其他图像替换。
但是在下载所有图像以获取位置后,它可以正常工作。
我知道并且已阅读上一篇关于getView不一致调用的帖子,但仍然无法解决问题。
`@Override public View getView(final int position,View convertView, final ViewGroup viewGroup){ ViewHolder viewHolder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.ondemand_grid_item,
null);
viewHolder = new ViewHolder();
viewHolder.title = ((TextView) convertView
.findViewById(R.id.ondemand_grid_item_title));
viewHolder.image = ((ImageView) convertView
.findViewById(R.id.ondemand_grid_item_image));
viewHolder.iconImage = ((ImageView) convertView
.findViewById(R.id.on_demand_trailer_icon));
viewHolder.showSelectedImage = (ImageView) convertView.findViewById(R.id.ondemand_grid_item_img);
viewHolder.showSelectedImage.setVisibility(View.INVISIBLE);
viewHolder.showSelectedImage.setSelected(true);
viewHolder.seasonNumber = (TextView) convertView.findViewById(R.id.ondemand_grid_item_season);
viewHolder.seasonNumber.setVisibility(View.INVISIBLE);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final OnDemandItem onDemandItem = getItem(position);
imageLoader.DisplayImage(onDemandItem.getPosterUrl(), viewHolder.image, onDemandItem.getGenrePlaceHolder());
showHideTrailerIcon(viewHolder, onDemandItem);
if (onDemandItem.getType() == AssetTypeEnum.SERIE) {
if (onDemandItem.getSeasonNumber() != null && !"".equals(onDemandItem.getSeasonNumber())) {
viewHolder.seasonNumber.setVisibility(View.VISIBLE);
viewHolder.seasonNumber.setText("Seizoen " + onDemandItem.getSeasonNumber());
}
}
viewHolder.title.setText(onDemandItem.getTitle());
if (selectedOndemandItemId == onDemandItem.getId()) {
convertView.findViewById(R.id.ondemand_grid_item_img).setVisibility(View.VISIBLE);
} else {
ImageView showSelectedImage = (ImageView) convertView.findViewById(R.id.ondemand_grid_item_img);
if (showSelectedImage != null) {
showSelectedImage.setVisibility(View.INVISIBLE);
}
}
return convertView;
}`
其中:imageLoader.DisplayImage(onDemandItem.getPosterUrl(),viewHolder.image,onDemandItem.getGenrePlaceHolder()); 是图像异步下载方法
答案 0 :(得分:1)
之前我遇到过同样的问题。这是我的伪代码解决方案(我使用monodroid,所以不确定它在java中是如何工作的,但算法应该清楚)
public override View GetView (int position, View convertView, ViewGroup parent)
{
View v = convertView;
int rev = 0;
lock(imageSync){
if(v == null){
LayoutInflater vi = (LayoutInflater)Context.GetSystemService (Context.LayoutInflaterService);
v = vi.Inflate (_textViewResourceId, null);
}
rev = Math.Random();
v.Tag = rev;
}
ImageView im = (ImageView)v.FindViewById (R.Id.image_view);
if (im != null) {
im.SetImageResource(R.Drawable.loading);
ImageLoader loader = GetLoader();
loader.OnImageLoadedListener=delegate (Drawable image, int backRev){
lock(imageSync){
if(((int)v.Tag) != backRev) return;
else im.SetImage(image);
}
};
loader.LoadImage(imageUrl, rev);
}
}
因此,每次Adapter询问我数据时,我都会用随机修订号标记一个视图。当我使用延迟加载时,我将此数字传递给加载程序,它在加载过程中保留它。加载完成后,我将比较加载程序返回的当前视图修订版本和修订版本。如果它们是等于的,那就可以了,我设置了图像。如果没有,这意味着在加载期间用户滚动我的ListView(GridView),当前View是另一个视图,而不是请求图像进入视图的视图。如果我将图像设置到其中,我将用被删除的图像替换图像,所以我只是忽略了这种情况。
答案 1 :(得分:0)
尝试使用setTag方法和imageview,我的解决方案就是这样,在适配器的getView方法中,setTag加载到imageview。
viewHolder.image.setTag(onDemandItem.getPosterUrl())
imageLoader.DisplayImage(onDemandItem.getPosterUrl(), viewHolder.image, onDemandItem.getGenrePlaceHolder());
在imageLoader类中,在将位图加载到imageview之前,检查imageview的getTag和url是否传递给loader类。
答案 2 :(得分:0)
我使用两个哈希映射解决了这个问题。当视图呈现时,会生成包含项目以及相应convertView对象的地图。您需要确保传入的OnDemandItem项上有唯一的ID,可以用来键入哈希图。
重新编写代码:
//class variables
private HashMap<String, ViewHolder> mapDemandItems = new HashMap<>();
private HashMap<String, View> mapConvertView = new HashMap<>();
public View getView(int position, View convertView, ViewGroup parent) {
OnDemandItem onDemandItem = getItem(position);
viewHolder = mapDemandItems.get(onDemandItem.getId());
if (viewHolder == null) {
viewHolder = new ViewHolder();
convertView = layoutInflater.inflate(R.layout.ondemand_grid_item,
null);
//set viewHolder values
mapDemandItems.put(onDemandItem.getId(), viewHolder);
mapConvertView.put(onDemandItem.getId(), convertView);
} else {
return mapConvertView.get(onDemandItem.getId());
}
...
return convertView;
}