9

Im having big troubles using a Target inside an adapter. Im confused about the documentation on the code

Objects implementing this class must have a working implementation of {@link #equals(Object)} and {@link #hashCode()} for proper storage internally. Instances of this interface will also be compared to determine if view recycling is occurring. It is recommended that you add this interface directly on to a custom view type when using in an adapter to ensure correct recycling behavior.

Im trying to use the Target in this way:

class CustomTarget implements Target {
    private ImageView imageView;

    public CustomTarget(ImageView imageView) {
        this.imageView = imageView;
    }

    @Override
    public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
        imageView.setImageDrawable(new RoundedAvatarDrawable(bitmap));
    }

    @Override
    public void onBitmapFailed(Drawable errorDrawable) {
        imageView.setImageDrawable(errorDrawable);
    }

    @Override
    public void onPrepareLoad(Drawable placeHolderDrawable) {
        imageView.setImageDrawable(placeHolderDrawable);
    }

    @Override
    public boolean equals(Object o) {
        return imageView.equals(o);
    }

    @Override
    public int hashCode() {
        return imageView.hashCode();
    }
}

 @Override
public View getView(int position, View v, ViewGroup parent) {
....
    RoundedAvatarDrawable r = new RoundedAvatarDrawable(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_avatar_seahorse));
    ImageCacheController.with(mContext).getPicasso().load(member.getPicture_url()).resize(100, 100).centerCrop().placeholder(r).error(r).into(new CustomTarget(viewHolder.ivAvatar));
....
}

It's doesn't work and the images change between each others randomly

Rodrigo Amaro Reveco
  • 4,932
  • 5
  • 22
  • 33
  • It seems your `getView()` is broken. Post your `getView()` method here. If you must, why not ask Eclipse to generate `equals()` and `hashCode()` method for you. **Right click > Source > Generate `hashCode()` and `equals()` ...** – M-Wajeeh Nov 25 '13 at 18:20
  • And BTW Picasso also accepts `ImageView` so you don't need to write this wrapper class. Just send `ImageView` in `into()` method. – M-Wajeeh Nov 25 '13 at 18:21
  • I'm using Target because I need a drawable wrapper named "RoundedAvatarDrawable" -> imageView.setImageDrawable(new RoundedAvatarDrawable(bitmap)); . That is for round the image as a circle. – Rodrigo Amaro Reveco Nov 25 '13 at 18:53
  • Why you are not posting your `getView()`? Strip it and post the code please. – M-Wajeeh Nov 25 '13 at 19:19

2 Answers2

12

You don't show your whole getView function, so without knowing how you use the viewHandler, here's my take on what's going on:

Your problem is that you're creating a new CustomTarget every time getView gets called. You are going against the point of having a Target object. Let me elaborate.

When a new download request is made, previous requests to the same target get stopped or don't result in a call to the Target's callbacks. (so if the Target gets reused for a different row in a list it doesn't get both rows' images).

You are using a new object for each request, effectively hinting Picasso that each request is for a different row so to speak. The doc says "Instances of this interface will also be compared to determine if view recycling is occurring", so since each request has a newly created CustomTarget object, no two requests will have the same object and a row recycle won't be detected.

You're also using viewHolder. In this case I think the viewHolder should be extending the Target interface (if you only have 1 image per row). This way everytime you request a download you can use the same object and not create a new one.

You're also delegating the implementation of your CustomTarget to the ImageView's implementation. Make sure that ImageView's equals and hashCode functions fullfill the requirements Picasso asks for.

Some info on how to implement equals and hashCode: What issues should be considered when overriding equals and hashCode in Java?

Community
  • 1
  • 1
frozenkoi
  • 3,228
  • 22
  • 33
  • `ImageView`'s implementations will be fine. – Jake Wharton Nov 26 '13 at 16:08
  • @Jake Is the recycle check also done with those two functions? If so, then I think the issue is prob. not due to his use of equals and hashCode and my answer is mostly irrelevant. Or is the check looking for the same exact object (using ==)? – frozenkoi Nov 26 '13 at 22:03
  • It is used by `WeakHashMap` which will use both methods for bucketing and then equality. – Jake Wharton Nov 27 '13 at 07:06
0

It seems your equals method is broken. You are comparing an imageview to a custom target. This might fix it:

public boolean equals(Object o) {
    if(o instanceof CustomTarget) {
        return ((CustomTarget) o).imageView.equals(this.imageView);
    }
    return super.equals(o);
}
Pepijn
  • 1,439
  • 17
  • 16