使用视图持有者模式时,毕加索会加载到错误的imageview中

Ben*_*ams 13 android picasso

我正在尝试使用Picasso库将外部图像加载到一行中ListView.我有一个ArrayAdapter如下习惯:

public class RevisedBusinessesAdapter extends ArrayAdapter<HashMap<String, String>> {

    Context context;
    int layoutResourceId;
    ArrayList<HashMap<String, String>> data = null;

    public RevisedBusinessesAdapter(Context context, int layoutResourceId,  ArrayList<HashMap<String, String>> data) {
        super(context, layoutResourceId, data);
        this.layoutResourceId = layoutResourceId;
        this.context = context;
        this.data = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        RevisedBusinessHolder holder = null;

        if (row == null) {
            LayoutInflater inflater = ((Activity) context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);
            holder = new RevisedBusinessHolder();
            holder.ivLogo = (ImageView) row.findViewById(R.id.ivBusinessLogo);
            row.setTag(holder);
        } else {
            holder = (RevisedBusinessHolder) row.getTag();
        }

        HashMap<String, String> business = data.get(position);

        String strLogoURL = business.get("logoURL");
        if (null != strLogoURL && !"".equals(strLogoURL)) {
            Picasso.with(this.context).load(strLogoURL).into(holder.ivLogo);        
        }

        return row;
    }

    static class RevisedBusinessHolder {
        ImageView ivLogo;
    }
}
Run Code Online (Sandbox Code Playgroud)

其中logoURL是远程图像的URL; 如果没有提供,ivBusinessLogo则设置一个本地src,而是显示.当我快速滚动时,毕加索将图像加载到错误中ImageView,最终我在列表中找到了它的多个副本.

这个问题的答案表明补充

Picasso.with(context).cancelRequest(holder.ivLogo);
Run Code Online (Sandbox Code Playgroud)

在现有的毕加索电话会议之前,但这并没有任何区别.如果我删除row == null检查并始终创建一个新视图,它似乎工作正常.但是,在完整版本中,还有四个文本视图和五个其他图像(从本地资源加载的小图标,而不是通过毕加索)需要在每个图像中进行更新getView.

有没有办法使用Android文档推荐的View Holder模式使其工作?

Jak*_*ton 22

你应该总是给Picasso打电话,即使你的URL是null.这样它就知道图像视图被回收了.

删除此if声明:

if (null != strLogoURL && !"".equals(strLogoURL)) {
Run Code Online (Sandbox Code Playgroud)

您还应该考虑使用占位符图像或错误图像,以便在没有URL时显示某些内容.

如果你坚持保留if声明(但你不应该!),你需要告诉Picasso通过调用回收图像视图cancelRequest:

Picasso.with(this.context).cancelRequest(holder.ivLogo);
Run Code Online (Sandbox Code Playgroud)

  • 删除`if`语句会让你给Picasso一个空的`String`,导致`IllegalArgumentException:Path不能为空.我是对的吗? (8认同)

gre*_*pps -1

在 Picasso.with().load().into() 语句后添加 else 语句。添加else holder.ivLogo.setImageBitmap(null);。或者使用占位符位图。

看过 Octa George 的解决方案后,最好始终holder.ivLogo.setImageBitmap(placeholderbitmap);在调用 Picasso 之前执行。否则,当毕加索“慢慢来”时,您首先会看到错误的回收图像。

  • 答案不正确,并且包含与问题相同的错误。在当今猖獗的复制/粘贴编程中,我想确保没有人使用此解决方案。 (6认同)