Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/189.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带LruCache的Android BaseAdapter存在一些ui问题_Android_Android Listview_Baseadapter_Android Lru Cache - Fatal编程技术网

带LruCache的Android BaseAdapter存在一些ui问题

带LruCache的Android BaseAdapter存在一些ui问题,android,android-listview,baseadapter,android-lru-cache,Android,Android Listview,Baseadapter,Android Lru Cache,我试图在基本适配器和LruCache的帮助下实现一个包含所有联系人映像的列表视图。但在屏幕上的长滚动上,所有图像(对应于该视图)都会在设置实际图像之前显示 例如:如果我们从第一个联系人滚动到第60个联系人,每页有5个项目的列表视图,在列表视图的第一个视图中,在显示第55个图像之前,1,6,11,16,21..51的图像会显示几毫秒 主要代码是 //Adapter public View getView(int position, View convertView, ViewGroup paren

我试图在基本适配器和LruCache的帮助下实现一个包含所有联系人映像的列表视图。但在屏幕上的长滚动上,所有图像(对应于该视图)都会在设置实际图像之前显示

例如:如果我们从第一个联系人滚动到第60个联系人,每页有5个项目的列表视图,在列表视图的第一个视图中,在显示第55个图像之前,1,6,11,16,21..51的图像会显示几毫秒

主要代码是

//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);
}
如何解决这个问题。
谢谢

当您向下滚动时,您的视图将被重新用于视图中的新列表位置。由于每次调用getView时都会启动一个新的BitmapManager任务,因此这些任务会排成一行,等待更新映像。当他们各自加载完位图后,他们会按顺序将其放入ImageView,这就是您看到的

看起来您试图使用对ImageView的引用来避免在位图被滚动出视图后使用它,但没有起作用的原因是适配器正在循环使用ImageView,因此引用仍然有效,即使实际上ImageView现在正用于不同的列表项

有不同的方法可以解决这个问题,但想到的最简单的方法是使用列表索引而不是ImageView本身构建BitmapManager。然后,在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);
}
//适配器
私有SparseArray ivMap=新SparseArray();
公共视图getView(int位置、视图转换视图、视图组父视图){
ImageView ImageView=(ImageView)convertView;
如果(imageView==null){
imageView=新的imageView(getActivity());
}否则{
//如果回收,请从地图中删除ImageView的上一个位置
int oldPosition=ivMap.indexOfValue(imageView);
如果(旧位置>=0){
ivMap.移除(旧位置);
}
}
//跟踪表示此位置的视图
ivMap.put(位置、图像视图);
int id=触点id[位置];
最终字符串imageKey=String.valueOf(contactId);
最终位图=cache.get(imageKey);
if(位图!=null){
设置图像位图(位图);
}否则{
Resources res=context.getResources();
BitmapManager bm=新的BitmapManager(ivMap、位置、分辨率、缓存);
setContext(getActivity());
bm.execute(id);
}
返回图像视图;
}
//位图管理器
@凌驾
受保护的void onPostExecute(位图){
//TODO自动生成的方法存根
试一试{
如果(isCancelled()){
位图=空;
}
if(位图!=null){
cache.put(String.valueOf(res),位图);
ImageView ImageView=ivMap.get(位置);
如果(imageView!=null){
设置图像位图(位图);
}
}
}捕获(例外e){
}
onPostExecute(位图);
}