Android ListView中的ImageViews显示以前加载的图像

时间:2014-12-09 23:14:56

标签: android listview android-asynctask android-imageview

我有一个Android ListView,它使用AsyncTask为每个ListViewItem下载不同的图片。每个图像在第一次下载时都会添加到ArrayList<Bitmap>,之后每次都会从ArrayList<Bitmap>访问。

如果我慢慢滚动ListView,每个图片都会按预期加载,但如果我开始滚动得更快,那么尚未下载图像的可见ListViewItems会开始显示项目中的图片已经滚动到屏幕顶部。

最终所有内容都会同步并且图片会通过onPostExecution来电更新,但出现了什么问题?如何防止以前的项目中的图片出现在ListView的较低项目中?< / p>

这是修剪过的代码:

private ArrayList<Bitmap> bitmapArray = new ArrayList<Bitmap>(500); 


@Override
public View getItemView(final int position, View convertView, final ViewGroup parent) {

    View itemView;
        if (convertView == null) {
            itemView = getInflater().inflate(ITEM_LAYOUT, parent, false);
        } else {
            itemView = convertView;
        }

        final ImageView mImageView = (ImageView) itemView.findViewById(R.id.app_component_joblistitemview_logo);

        if (bitmapArray.size()>position && bitmapArray.get(position)!=null) {
            // Item exists at bitmapArray[position], use it
            Log.i("JobListView","Setting Existing for Position:"+position);
            mImageView.setImageBitmap(bitmapArray.get(position));
        } else {
            // Have not downloaded this ListView[position] logo yet        
            bitmapArray.add(position,null); // add temporary null value until the image is downloaded
            mImageView.setImageBitmap(null);
            new DownloadImageTask().execute(logo.getLogoUUID(), mImageView, position);
        }

        return itemView;
    }


    // This AsyncTask downloads an image / logo from a specified URL and then updates the specified ImageView
    private class DownloadImageTask extends AsyncTask<Object, Void, Bitmap> {

        ImageView imageView;
        Integer listViewPosition;

        @Override
        protected Bitmap doInBackground(Object... params) {
            String urlString = "http://www.myimages.com/something/"+params[0].toString();

            this.imageView = (ImageView)params[1];
            this.listViewPosition = (Integer)params[2];

            try {
                URL url = new URL(urlString);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setDoInput(true);
                connection.connect();
                InputStream input = connection.getInputStream();
                Bitmap myBitmap = BitmapFactory.decodeStream(input);
                bitmapArray.set(listViewPosition,myBitmap);
                return myBitmap;

            } catch (Exception e) {
                // Log exception
            }
        }

        protected void onPostExecute(Bitmap result) {
            imageView.setImageBitmap(result);
        }
    }

1 个答案:

答案 0 :(得分:0)

else {
        // other methods, then set tag and run task
        mImageView.setTag(logo.getLogoUUID());
        new DownloadImageTask().execute(logo.getLogoUUID(), mImageView, position);
    }

int uuid=-1;

protected Bitmap doInBackground(Object... params) {
        uuid=params[0];
        //other methods
}

protected void onPostExecute(Bitmap result) {
    //if tag exists check validity
    if(imageView.getTag()==null && imageView.getTag().equals(uuid))
        imageView.setImageBitmap(result);
}

假设您有2张照片 - 第一张10像素,第二张FHD。当你的项目需要FHD位图下载器开始下载,obvius。当你仍然滚动并且这个项目被“滚出”时,它会在下面(或上面,取决于滚动方向)出现(作为再循环/转换视图)。然后你设置下载10px位图,这是更快。 10 px设置,但以前asynctask下载fhd图片仍在运行,仍然保持对imageView的引用。因此,当下载fhd时,它将替换此10像素。对于解决方法,您可以设置任何identyfying参数,您的“uuid”可能是完美的

listView和适配器的工作原理您可以阅读herehere - 检查方法convertView中的getView是什么,您可以使用ViewHolder模式

PS。我看到你的代码中有一些空指针,因为清理?例如:

View itemView;
final ImageView mImageView = //itemView is just created, findViewById will throw NPE
    (ImageView) itemView.findViewById(R.id.app_component_joblistitemview_logo);