为什么错误的图像得到加载的ListView偶尔? [英] Why are wrong images getting loaded in ListView occasionally?

查看:337
本文介绍了为什么错误的图像得到加载的ListView偶尔?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个列表视图,它加载图像异步每一个细胞。当我试图慢慢地向下滚动(加载当前视图中的所有图像之后),它完美的作品。 但是,当我尝试向下滚动,他们甚至加载之前,然后向上滚动,我面对这个问题。细胞开始出现不对应于它们的图像。

I have a listview which loads images in every cell in async. When I try to scroll down slowly(after all the images in the current view are loaded), it works flawlessly. But when I try to scroll down before they are even loaded and scroll up, I face this issue. The cells start to show up images which don't correspond to them.

我的getView方法是这样的:

My getView method looks like this:

public View getView(final int position, View convertView, ViewGroup parent) {

    // TODO Auto-generated method stub

    View rowView = null;

    if(convertView == null) {
        rowView = inflater.inflate(R.layout.list_posts_item, null);
        final Holder holder=new Holder();
        holder.tvTitle=(TextView) rowView.findViewById(R.id.tvTitleNamePost);
        holder.ivPrimaryImage=(ImageView) rowView.findViewById(R.id.ivPrimaryImage);
        holder.tvLocality=(TextView) rowView.findViewById(R.id.tvLocalityPosts);
        holder.tvDateCreated=(TextView) rowView.findViewById(R.id.tvDateCreated);
        rowView.setTag(holder);
    }else {
        rowView=convertView;
    }

    Holder holder = (Holder)rowView.getTag();
    holder.ivPrimaryImage.setId(position);
    holder.ivPrimaryImage.setTag(listOfPosts.get(position).getPostId());
    holder.ivPrimaryImage.setImageBitmap(null); // Added for flickering issue
    holder.tvTitle.setText(listOfPosts.get(position).getTitle());
    holder.tvLocality.setText(listOfPosts.get(position).getLocality());
    holder.tvDateCreated.setText(listOfPosts.get(position).getCreatedDate());
    postId = listOfPosts.get(position).getPostId();
    Image image = new Image();
    image.setImg(holder.ivPrimaryImage);

    if (!"N".equalsIgnoreCase(listOfPosts.get(position).getHasImage()) ) {
        if(!tagsCaching.containsKey(postId))
            new GetPrimaryImages().execute(image);
        else
             holder.ivPrimaryImage.setImageBitmap(tagsCaching.get(postId));
    }

    return rowView;
}

和我的异步调用的类看起来是这样的:

And my Async call class looks like this:

public class GetPrimaryImages extends AsyncTask<Image, Void, Bitmap> {

ImageView imageView = null;
    protected Bitmap doInBackground(Image... images) {
    this.imageView=images[0].getImg();



        // Building Parameters
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("postid",(String)(this.imageView.getTag()) ));


             json = jsonParser.makeHttpRequest(CommonResources.getURL("get_primary_image"),
                    "POST", params);


        if(json == null){
            return null;
        }
        Log.d("Fetching Image",imageView.getTag()+ json.toString());
        tagsDownloaded.add((String)imageView.getTag());
        // check for success tag
        String TAG_SUCCESS = "success";
        try {
            int success = json.getInt(TAG_SUCCESS);

            if (success == 0) {
               image =  json.getString("primaryimage");

            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return getImage(image);

    }

    /**
     * After completing background task Dismiss the progress dialog
     * **/
    protected void onPostExecute(Bitmap result) {
        tagsCaching.put((String)imageView.getTag(), result);
        imageView.setImageBitmap(result);

    }

    public Bitmap getImage(String imageString) {
        if("null".equalsIgnoreCase(imageString)){
            return null;
        }else{
            byte[] decodedString = Base64.decode(imageString, Base64.DEFAULT);
            Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
            //image.setImageBitmap(decodedByte);
            return decodedByte;
        }

    }


}

编辑:

我添加了一个新的实例变量持有人:

I added a new instance variable to Holder:

public class Holder
{
    TextView tvTitle;
    ImageView ivPrimaryImage;
    TextView tvLocality;
    TextView tvDateCreated;
    int position;
}

在getView设置相同的:     holder.position =位置; 并通过持有对象的异步任务:     新GetPrimaryImages(位置,架).execute(图像);

Set the same in the getView: holder.position = position; And passed the holder object to the Async task: new GetPrimaryImages(position, holder).execute(image);

和修改了异步调用类,如下所示: 1.添加取消对HTTP调用 2.改变了onPostExecute方法

And modified the Async call class as follows: 1. Added cancel to the http call 2. Changed the onPostExecute method

  public class GetPrimaryImages extends AsyncTask<Image, Void, Bitmap> {

    int mPosition;
    Holder mHolder;
    public GetPrimaryImages(int position, Holder holder){
        mPosition = position;
        mHolder = holder;
    }

    ImageView imageView = null;
    protected Bitmap doInBackground(Image... images) {
    this.imageView=images[0].getImg();



        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("postid",(String)(this.imageView.getTag()) ));


        JSONObject json;
        if(mHolder.position == mPosition)
             json = jsonParser.makeHttpRequest(CommonResources.getURL("get_primary_image"),
                    "POST", params);

        else {
            json = null;
            cancel(true);
        }

        // check log cat fro response
        if(json == null){
            return null;
        }
        Log.d("Fetching Image",imageView.getTag()+ json.toString());
        tagsDownloaded.add((String)imageView.getTag());
        // check for success tag
        String TAG_SUCCESS = "success";
        try {
            int success = json.getInt(TAG_SUCCESS);

            if (success == 0) {
               image =  json.getString("primaryimage");

            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return getImage(image);

    }


    protected void onPostExecute(Bitmap result) {
        if (mHolder.position == mPosition) {
            tagsCaching.put((String) imageView.getTag(), result);
            imageView.setImageBitmap(result);
        }

    }

    public Bitmap getImage(String imageString) {


        //needs to wait
        if("null".equalsIgnoreCase(imageString)){
            return null;
        }else{
            byte[] decodedString = Base64.decode(imageString, Base64.DEFAULT);
            Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
            //image.setImageBitmap(decodedByte);
            return decodedByte;
        }

    }


}

这似乎是工作。 :)

It seems to be working. :)

现在我的疑问是,这将是缓存图像的最佳方法是什么?应该是它写入文件?并从中我每次向上滚动阅读它?

Now my doubt is what would be the best way to cache the images? Should be writing it to a file? and reading it from it every time I scroll up?

推荐答案

现在的问题是,当你的异步任务结束其后台运行,它是有联系的已回收来保存您的收藏的另一个元素的元素。

The problem is, while your async task ends its background operation, the element it was linked to has been recycled to hold another element of your collection.

让我们关注的元素的位置,让我们说你的列表视图可以显示多达4个元素。

Let's focus on elements position, and let's say your listview can display up to 4 elements.

第一次调用列表视图getview对于第一4个元素,和四个asynctasks创建和运行。 然后滚动到shouw位置11 - 15,和第一元件(一个涉及到位置1)被再循环用于位置11的AsyncTask的之前结束。

The first time the listview calls getview for the first 4 elements, and four asynctasks are created and run. Then you scroll to shouw positions 11 - 15, and the first element (the one related to position 1) gets recycled for position 11 before the asynctask ends.

然后AsyncTask的结束,你看到的是后11后1相关的位图相关的图像。

Then the asynctask ends, and what you see is the image related to post 11 with the bitmap related to post 1.

一个方法来避免这种情况是知道的AsyncTask的该观点被回收,在这个古老的职位从卢卡斯Rocha的建议。

A way to avoid this is knowing in the asynctask that the view was recycled, as suggested in this old post from Lucas Rocha.

性能提示与列表视图

检查列表视图是如何工作太职位的见解:

Check the post for insights on how listview works too:

输入图像的描述在这里

这篇关于为什么错误的图像得到加载的ListView偶尔?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆