我正在尝试使用基本适配器和LruCache实现所有联系人图像的列表视图。但是在屏幕上的长滚动中,在设置实际图像之前会显示所有图像(对应于该视图)。
例如:每页有5个项目的列表视图,如果我们从第一个联系人滚动到第60个,在列表视图的第一个视图中,1,6,11,16,21..51的图像显示几毫秒之前第55幅图像显示
主要代码是
//Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = (ImageView) convertView;
if(imageView == null){
imageView = new ImageView(getActivity());
}
int id = contactId[position];
final String imageKey = String.valueOf(contactId);
final Bitmap bitmap = cache.get(imageKey);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
Resources res = context.getResources();
BitmapManager bm = new BitmapManager(imageView, res, cache);
bm.setContext(getActivity());
bm.execute(id);
}
return imageView;
}
BitmapManager发布执行代码
@Override
protected void onPostExecute(Bitmap bitmap) {
// TODO Auto-generated method stub
try{
if(isCancelled()){
bitmap = null;
}
if(imageViewReference != null && bitmap != null){
ImageView imageView = imageViewReference.get();
imageView.setImageBitmap(bitmap);
cache.put(String.valueOf(res), bitmap);
if(imageView != null){
imageView.setImageBitmap(bitmap);
}
}
}catch(Exception e){
}
super.onPostExecute(bitmap);
}
如何解决这个问题。 感谢
答案 0 :(得分:1)
向下滚动时,您的视图会重新用于进入视图的新列表位置。由于每次调用getView时都会启动一个新的BitmapManager任务,因此任务会排成一行,等待更新映像。当他们每个人完成加载他们的位图时,他们按顺序将它放入ImageView,这就是你所看到的。
看起来你试图使用ImageView的引用来避免在滚动视图之后使用位图,但是没有用的原因是适配器正在回收你的ImageViews,所以即使实际上ImageView现在也用于不同的列表项,该引用仍保持有效。
有不同的方法可以解决这个问题,但最简单的想法是使用列表索引构建BitmapManager,而不是ImageView本身。然后在getView中,您可以保留在哪些位置使用哪些视图的映射。当BitmapManager完成时,检查您刚刚加载到缓存中的位置是否存在当前ImageView。如果没有,那就什么都不做。
以下是一些显示我正在谈论的内容的代码。我没有尝试过,所以如果有错误就道歉。
//Adapter
private SparseArray<ImageView> ivMap = new SparseArray<ImageView>();
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = (ImageView) convertView;
if(imageView == null){
imageView = new ImageView(getActivity());
} else {
// If recycled, remove the ImageView's previous position from map
int oldPosition = ivMap.indexOfValue(imageView);
if (oldPosition >= 0) {
ivMap.remove(oldPosition);
}
}
// Keep track of which view is representing this position
ivMap.put(position, imageView);
int id = contactId[position];
final String imageKey = String.valueOf(contactId);
final Bitmap bitmap = cache.get(imageKey);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
Resources res = context.getResources();
BitmapManager bm = new BitmapManager(ivMap, position, res, cache);
bm.setContext(getActivity());
bm.execute(id);
}
return imageView;
}
//BitmapManager
@Override
protected void onPostExecute(Bitmap bitmap) {
// TODO Auto-generated method stub
try{
if(isCancelled()){
bitmap = null;
}
if(bitmap != null){
cache.put(String.valueOf(res), bitmap);
ImageView imageView = ivMap.get(position);
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}catch(Exception e){
}
super.onPostExecute(bitmap);
}