android - ListView 显示错误的图像

标签 android listview lazy-loading imageview android-arrayadapter

我有一个带有 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.

不过,您可以做的是在列表适配器中保留一个位图缓存。像这样:

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;
}

关于android - ListView 显示错误的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6081497/

相关文章:

ios - 带有初始值设定项的惰性属性

Android插页式广告添加测试设备?

c# - 组中 ListView 项的索引

entity-framework - 禁用延迟加载时,如何仅将导航属性的特定属性包含到 Entity Framework 的查询中?

WPF:如何 Hook 到 ListView 的 ItemsSource CollectionChanged 通知?

c# - 选择ListView的特定列并在C#.net中的新消息框中打印

javascript - 如何在 Angular 的延迟加载模块中保持表单状态?

android - 在Android中,proxy_gps_nmea_cb()有什么用?

android - 显示不支持的自定义属性的错误

android - 旋转视频搞砸了 MediaControls,android