listview中的错误图像,因为imageview被回收

时间:2014-11-08 18:28:19

标签: android-listview picasso android-async-http

代码如下所示:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final Contact currContact = getItem(position);

    final ViewHolder viewHolder;
    if (convertView == null) {
        viewHolder = new ViewHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.contact_item, parent, false);

        viewHolder.profileIV = (ImageView) convertView.findViewById(R.id.profileIV);
        viewHolder.nameTV = (TextView) convertView.findViewById(R.id.nameTV);

        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
**************************PER JAKE WHARTON's RESPONSE******************************************
        Picasso.with(getContext()).cancelRequest(viewHolder.profileIV);
    }

    String currName = currContact.getName();

    /* 1 
       Asynchronously GETs https://ajax.googleapis.com/ajax/services/search/images? 
       rsz=8&start=0&v=1.0&imgsz=medium&imgtype=linear&q=(currName) */
    APIclient.getImageJson(getContext(), currName, new JsonHttpResponseHandler() {
        @Override
        public void onSuccess(int statusCode, Header[] headers, JSONObject imgJson) {
            try {
                JSONObject responseDataValue = imgJson.getJSONObject("responseData");
                JSONArray resultsValue = responseDataValue.getJSONArray("results");
                JSONObject result = resultsValue.getJSONObject(0);
                String imgUrl = result.getString("url");

                // 2
                Picasso.with(getContext()).load(imgUrl).into(viewHolder.profileIV);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
  1. 启动异步调用,用户向下滚动。
  2. 调用完成,获取图像网址,Picasso发出另一个GET请求来渲染图像,但由于回收而在错误的imageview中
  3. 我知道解决这个问题的唯一方法是发出第一个GET请求(获取图像链接)SYNCHRONOUS,阻止ui以确保在加载图像之前不再调用getView。有没有更好的方法解决这个问题?提前谢谢了。

1 个答案:

答案 0 :(得分:4)

您看到此行为的原因是您在发出另一个异步请求后才调用Picasso对象。这意味着毕加索无法知道视图是否被回收用于新项目。

解决此问题的最简单方法是向Picasso添加一个调用,取消现有的回收视图请求。

Picasso.with(getContext()).cancelRequest(viewHolder.profileIV)

这应该在APIclient.getImageJson调用的 之外完成,以便在调用适配器时它同步运行。