3

我有一个ListView与一个ArrayAdapter持有行与一个图像和一个字符串。这工作得很好,直到我决定加载的图像速度很慢,因此我无法在显示列表之前加载图像。所以我开始使用AsyncTask在单独的线程中加载图像。Listview显示错误的图像

我对结果非常满意,直到我开始滚动列表。错误的图像被加载,它看起来不像是一段时间后图像的问题。如果我尝试对列表进行排序,则问题非常糟糕,并且没有任何图像位于右侧。

任何想法我做错了什么?

public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 
     ImageView imageView; 
     TextView textView; 
     if (v == null) { 
      LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
        Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.drink_list_row, null); 
     } 

     Drink drink = allItems.get(position); 
     if (drink != null && v != null) { 
      imageView = (ImageView) v.findViewById(R.id.picture); 
      textView = (TextView) v.findViewById(R.id.drinkName); 
      imageView.setVisibility(View.GONE); 
      loadImageBitmap(drink, imageView); 
      textView.setText(drink.getName()); 

      if (subItems != null && subItems.contains(drink)) { 
       textView.setVisibility(View.VISIBLE); 
       imageView.setVisibility(View.VISIBLE); 
      } else { 
       textView.setVisibility(View.GONE); 
       imageView.setVisibility(View.GONE); 
      } 
     } 
     return v; 
    } 

回答

5

的问题来自于您的convertView:它是在整个列表中使用相同的单个实例,所以当你的异步加载完成后,图像被改变时ListView控件正试图使用​​画一个不同的项目相同的convertView(或者在这种情况下,它的子图像视图)。

painting position 1, uses placeholder, starts loading image 1 asynchronously 
painting position 2, uses placeholder, starts loading image 2 asynchronously 
image 1 loading is complete, calling setImageBitmap on imageView 
painting position 3, uses image 1, starts loading image 3 asynchronously 
etc. 

虽然你可以做的是保持listadapter中的位图缓存。这样的事情:

private Bitmap[] bitmapList; 
private Bitmap bitmapPlaceholder; 

private void initBitmapListWithPlaceholders(){ 
// call this whenever the list size changes 
// you can also use a list or a map or whatever so you 
// don't need to drop all the previously loaded bitmap whenever 
// the list contents are modified 
    int count = getListCount(); 
    bitmapList = new Bitmap[count]; 
    for(int i=0;i<count;i++){ 
     bitmapList[i]=bitmapPlaceholder 
    } 
} 

private void onBitmapLoaded(int position, Bitmap bmp){ 
// this is your callback when the load async is done 
    bitmapList[position] = bmp; 
} 

public View getView(int position, View convertView, ViewGroup parent) { 
    View v = convertView; 
    ImageView imageView; 
    TextView textView; 
    if (v == null) { 
     LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
       Context.LAYOUT_INFLATER_SERVICE); 
     v = vi.inflate(R.layout.drink_list_row, null); 
    } 

    Drink drink = allItems.get(position); 
    if (drink != null && v != null) { 
     imageView = (ImageView) v.findViewById(R.id.picture); 
     textView = (TextView) v.findViewById(R.id.drinkName); 
     imageView.setVisibility(View.GONE); 
     imageView.setImageBitmap(bitmapList[position]); 
     loadImageBitmap(drink, position); // this should call onBitmapLoaded(int position, Bitmap bmp) when finished to update the bitmapList and replace the placeholder 
     textView.setText(drink.getName()); 

     if (subItems != null && subItems.contains(drink)) { 
      textView.setVisibility(View.VISIBLE); 
      imageView.setVisibility(View.VISIBLE); 
     } else { 
      textView.setVisibility(View.GONE); 
      imageView.setVisibility(View.GONE); 
     } 
    } 
    return v; 
} 
+0

我遇到了这个问题,并以类似的方式解决它。不过,我现在看到图像不会出现在listview项目中,直到项目被滚出并返回到视图中。关于如何强制物品更新的任何想法? – cacois 2011-06-12 16:10:24

+0

@cacois开始新的问题,但在列表视图无效将工作。 – Warpzit 2012-04-30 09:23:35