5

I didn't find an answer here, here and here.

I have an activity that shows list of posts (with or without images). When I scroll down and scroll up or refresh the list using SwipeRefreshLayout some of the images may disapper. I use RecyclerView to show list of posts and Picasso to load images. Here is my adapter binding:

@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    // <...>
    if (item.getPhoto() != null) {
        Picasso.with(context)
                .load(item.getPhoto())
                .into(holder.mPostPhoto);
    } else {
        holder.mPostPhoto.setImageDrawable(null);
        holder.mPostPhoto.setVisibility(View.GONE);
    }
}

I send HTTP request to get posts and when I have new data I call PostsAdapter:

public void addAll(List<PostResponse> items) {
    this.items.clear();
    this.items.addAll(items);

    notifyDataSetChanged();
}

In MainActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // <...>
    mPostAdapter = new PostAdapter();
    mPosts.setLayoutManager(new LinearLayoutManager(MainActivity.this));
    mPosts.setAdapter(mPostAdapter);

    mPostsSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            updatePosts();
        }
    });

    updatePosts();
}

private void updatePosts() {
    new Api(this).getPosts(new GetPostsCallback(this) {
        @Override
        public void onSuccess(final Paging<PostResponse> paging) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mPostAdapter.addAll(paging.getData());
                    mPostsSwipeRefresh.setRefreshing(false);
                }
            });
        }
    });
}

I find it's pretty basic, I don't understand why images disappear time after time. My list is not long and images resized before the upload to the server, they shouldn't use much memory. And the worst, when they disappear, they don't reload. They may reload only after I scroll down and up...

  • Please explain me why it happens.
  • How can I fix this problem?

Thanks!

Community
  • 1
  • 1
Andrei
  • 42,814
  • 35
  • 154
  • 218
  • it is hard to say why is this happening with the code you posted. Could you share a little bit more ? Do you have any specific configuration policy for picasso? – Blackbelt Nov 05 '16 at 18:04
  • @Blackbelt please see an update. I don't have any specific configuration for anything. It's very basic: get posts from the server, each post has image url, use picasso to load image to ImageView by url. – Andrei Nov 05 '16 at 18:19
  • it looks good - if you log `item.getPhoto()` ? – Blackbelt Nov 05 '16 at 18:24
  • @Blackbelt I checked `item.getPhoto()` it's there... – Andrei Nov 05 '16 at 18:27

5 Answers5

10

I ran into this issue as well, but didn't want to disable the recycling. I found that by explicitly setting the ImageView visibility to View.VISIBLE before making the call to Picasso, the images loaded even after scrolling:

holder.image.setVisibility(View.VISIBLE);
Picasso.with(context)
    .load(imgUrl)
    .into(holder.image);
William Brawner
  • 1,470
  • 17
  • 15
  • 1
    this is the right answer , please accept it so that others know it works – Kaustubh Bhagwat Sep 21 '17 at 08:51
  • 1
    @Billy Brawner, man thank you so much.. you saved my day! This should be the correct answer – Shahriar Siraj Snigdho Oct 20 '17 at 18:51
  • @William its does work perfectly but could you explain what was the reason for the error. – chris Dec 07 '20 at 07:06
  • 1
    @chris it's been a few years since I last looked at this but in the sample code from the question at least, the ImageView's visibility is being set to `View.GONE` if there isn't any image, but it's never being set back to `View.VISIBLE` when the view is reused in the future. Since the RecyclerView will only create the views once, and then recycle them (hence the name), that visibility state is persisted even though the data associated with the view has changed – William Brawner Dec 08 '20 at 14:20
3

So, apparently RecyclerView was recycling items from my list and for some reason it couldn't reload images after that. Good question "why?"... Maybe because I did something wrong, not sure. This helped me:

recyclerView.getRecycledViewPool().setMaxRecycledViews(0, 0);

Basically you are turning off items recycling. It works for me because I don't render huge lists of items.

Andrei
  • 42,814
  • 35
  • 154
  • 218
2

If you are using if condition in adapter then try below code

    if (model.image == null || model.equals(""))
        viewHolder.ivIndieImage.setVisibility(View.GONE);
    else{
        viewHolder.ivIndieImage.setVisibility(View.VISIBLE);
      }

try to setVisibility visible of the image.

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
Rohan Lodhi
  • 1,385
  • 9
  • 24
0

You missed one thing in the onBindViewHolder. In the else part you are changing the visibility to View.GONE but in the If part you are not making it visible again. So, in recycler view the views are getting recycled means there data is getting changed but If you modify any property it will remain same for that view and it will be seen in the other items that are being shown using the same recycled view.

hiten pannu
  • 186
  • 1
  • 6
0

I was able to fix this issue by removing the resize and center crop methods of the same, somehow they were taking too much memory and it was leading to messing up the image loading process

Huzefa Gadi
  • 1,129
  • 1
  • 7
  • 11