Nikita Kulikov
Nikita Kulikov

Reputation: 156

RecyclerImageViewHolder load item in new thread

I try move my load logic in new thread and ImageView in RecyclerImageViewHolder change very quikly. I try interrupt thread and i try check before set image, but it not work... I don't understand why it not work

demonstration

 //One view - one thread
    private Thread imageLoadThread = null;

    public AuthorRecyclerViewHolder(LinearLayout itemView, Activity activity) {
        super(itemView);
        this.view = itemView;
        itemView.findViewById(R.id.card_view).setOnClickListener(this);
        this.activity = activity;
    }

    public AuthorRecyclerViewHolder setItem(AuthorObject ao) {
        this.ao = ao;

        //Find image
        iv = (ImageView) view.findViewById(R.id.imageView);

        //Clear
        if (imageLoadThread != null)
            imageLoadThread.interrupt();
        iv.clearAnimation();
        iv.setImageResource(R.drawable.notfoundmusic);

        //Set content
        setImageOnItemView(activity, iv, false);
        ((TextView) view.findViewById(R.id.description)).setText(ao.description);
        ((TextView) view.findViewById(R.id.head_author)).setText(ao.name);
        return this;
    }


    public void setImageOnItemView(final Activity activity, final ImageView iv, boolean isBigPicture) {
        final Animation vis = AnimationUtils.loadAnimation(activity, R.anim.alphavisible);
        final ImageResource ir = isBigPicture ? ao.bigImage == null ? ao.smallImage : ao.bigImage : ao.smallImage == null ? ao.bigImage : ao.smallImage;
        if (ir != null)
            this.imageLoadThread = ir.getImage(this);
        else {
            iv.setImageResource(R.drawable.notfoundmusic);
            iv.startAnimation(vis);
            iv.setAlpha(1.0F);
        }
    }


    @Override
    public void recieveResource(final @Nullable Bitmap bitmap, final String id) {
        final Thread thisThread = Thread.currentThread();

        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {

                final Animation vis = AnimationUtils.loadAnimation(activity, R.anim.alphavisible);
                final Animation unvis = AnimationUtils.loadAnimation(activity, R.anim.alphaunvisible);
                iv.clearAnimation();

                if (thisThread.isInterrupted())
                    return;
                if (id.substring(id.lastIndexOf("_") + 1).equals(String.valueOf(ao.authorId)))
                    if (bitmap != null) {
                        new Handler().postDelayed(new Runnable() {
                            public void run() {
                                iv.setImageBitmap(bitmap);
                                iv.setAnimation(vis);
                            }
                        }, unvis.getDuration());
                        iv.setAlpha(1.0F);
                        iv.startAnimation(unvis);
                    } else {
                        iv.startAnimation(vis);
                        iv.setAlpha(1.0F);
                    }
            }
        });
    }

Upvotes: 0

Views: 419

Answers (1)

Knossos
Knossos

Reputation: 16038

The error is to do with the way that RecyclerView reuses its ViewHolders..

Basically, here is a rundown of what is happening to one arbitrary ViewHolder in your view.

  1. Created
  2. Populated with data (image thread started to download image #1)
  3. Scroll down
  4. New data populated from dataset (image thread started to download image #2)
  5. Scroll down
  6. New data populated from dataset (image thread started to download image #3)
  7. You stop scrolling
  8. Image #1 downloaded and shown
  9. Image #2 downloaded and shown
  10. Image #3 downloaded and shown

This is why you see multiple images loading after scrolling.

There isn't an easy fix for this. You need to tell your image downloading thread to stop if the underlying content for the ViewHolder changes.

Upvotes: 2

Related Questions