我有一个带有ArrayAdapter的ListView,其中包含带有图像和字符串的行。直到我确定图像的加载速度变慢,这样我才能在显示列表之前无法加载图像,这样效果很好。因此,我开始使用加载图像到单独的线程中AsyncTask。
在开始滚动列表之前,我对结果感到非常满意。加载了错误的图像,看起来好像不是图像稍后出现的问题。如果我尝试对列表进行排序,问题将变得非常严重,并且没有图像在右行。
关于我在做什么错的任何想法?
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; }
问题来自于您的convertView:它是整个列表中使用的同一实例,因此,当异步加载完成时,当listview尝试使用相同的convertView绘制其他项目时,图像会更改(或在这种情况下) ,其子imageView)。
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; }