3

When dealing with many scrolling images, you have to avoid the problem of loading while skimming, while the user is fast scrolling. The simplest and often best solution is remarkably simple:

just introduce a small delay (say .350) before doing anything.

If the image is already in cache, just load it. Otherwise just wait a bit - and then proceed totally normally.

With the magnificent Picasso, depressingly it looks like there is a fork which in fact does just this, it has a "withDelay" option** (see https://github.com/square/picasso/issues/248)

I'm scared of forks.

But is it possible to do this in Picasso, perhaps using a custom "Target"? So,

My ordinary Picasso call (at the end of a getView...)

Picasso.
  with(State.mainContext).
  load(imageFile.getUrl()).
  placeholder(R.drawable.default).
  noFade().
  into(v.im);

whereas I think I want something like this .......

Picasso.
  with(State.mainContext).
  load(imageFile.getUrl()).
  placeholder(R.drawable.default).
  noFade().
  into(new Target()
     {
     simply wait .350 before proceeding completely normally...
     });

I can't do it, can anyone do it?

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • btw I can very easily do this in iOS so I'm happy to trade for anyone who needs it in iOS :-) – Fattie Sep 20 '14 at 15:25
  • First of, you need to hold onto the `Target`, as explained [here](https://github.com/square/picasso/issues/38#issuecomment-23793609). – mbmc Sep 20 '14 at 15:30

2 Answers2

10

edit:

so apparently the guys at Square just starting to move forward with their stuff. https://github.com/square/picasso/pull/665

so Lucasr took over and re-organize some of the code. Now the pause/resume can be done in groups, all requests have a DEFAULT_GROUP and apparently the ScrollListener idea was ditched because it's too much of a simple implementation for them to bother, but it's the same code @a.bertucci posted.

public class SampleScrollListener implements AbsListView.OnScrollListener {
  private final Context context;
  private static final Object scrollTag = new Object(); // this can be static or not, depending what u want to achieve

  public SampleScrollListener(Context context) {
    this.context = context;
  }

  @Override
  public void onScrollStateChanged(AbsListView view, int scrollState) {
    final Picasso picasso = Picasso.with(context);
    if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
      picasso.resumeTag(scrollTag);
    } else {
      picasso.pauseTag(scrollTag);
    }
  }

  @Override
  public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                       int totalItemCount) {
    // Do nothing.
  }
}

this implementation goes with the idea that you'll tag your requests with the context apparently, but just as easily you could tag with default or your custom tags.

original answer:

There's already a PullRequest on Picasso for this feature here: https://github.com/square/picasso/pull/561

It's a bit different from what you suggested, but it works great (I'm using on my app). You have an option to pause/resume dispatching the images to the ImageViews and use an onScrollListener to pause n resume it.

The code for it is simply:

listView.setOnScrollListener(new PicassoScrollListener(context));

I agree that forks are annoying because they can get outdated, but can fork it yourself, and keep it up-to-date until it gets merged on Picasso.

  • fork Picasso original
  • add this as a remote https://github.com/sockeqwe/picasso and fetch it
  • create your branch out of picasso/master and cherry pick those 10 commits from sockeqwe/picasso
  • pull picasso/master as often as you want

It's not ideal, but the programming is all done for you and it works very well.

Alternatively you can use my app fork compile 'com.eyeem.picasso:picasso:2.3.3-SNAPSHOT' and keep an eye on that pull request until it gets merged and you revert.

Budius
  • 39,391
  • 16
  • 102
  • 144
  • Fascinating; if you notice my long comments below a.bertucci's answer. I'm interested if "pause" means **"DO NOT START ANY NEW REQUESTS"**, and/or does it mean **"PAUSE IN GETTING ANY REQUESTS ALREADY BEGUN"**. – Fattie Sep 24 '14 at 09:20
  • I did not noticed your long comment. I did not enter their code, but as far as I've been seen from my own tests (feel free to download our app and see it for your self https://play.google.com/store/apps/details?id=com.baseapp.eyeem) it simply stops currently dispatching the drawables to the screen. That means that all the images still will download/cache. The main idea of this change is regarding scrolling performance, and what impacts the performance is that moment when the image view needs to redraw the whole Drawable on screen for the first time. – Budius Sep 24 '14 at 09:26
  • AHHHHHHHHHHH ... so, in the example, it will still attempt to begin all 703 downloads, on the download thread. (Which is fine.) But it completely stop doing anything with the drawables. FANTASTIC!! You rock :) – Fattie Sep 24 '14 at 09:34
  • yes that's correct. I saw you already tick as correct answer bounty and all that good stuff. But remember, that's not released yet (hopefully soon, but they don't give ETAs). They might take some time, do some bug fix or something like this. So if you want to use the feature now, you still have to fork their stuff. – Budius Sep 24 '14 at 09:53
  • I've got you. Mainly I develop for iOS, so we are scared of forks :) You know, if you see that final version is released, perhaps you should leave a note here -- I just mean since your answer will be so useful to other internauts! CHEERS! – Fattie Sep 24 '14 at 11:06
  • 1
    @JoeBlow are you kidding me? I post the correct answer and you accepted this answer with the code from my answer? :/ Cm'on @Budius! – a.bertucci Sep 24 '14 at 13:23
  • wow. let's not fight about it guys. @a.bertucci for sure did answer. But if you look at all details I posted 4 days ago about a PR from couple months ago. Reading it you can see the guys organizing how to implement the feature, refactored some stuff and made into a new PR that was created 23hours, and that is the PR from your answer. And that's the PR I linked when I edited my answer. Also the code that you and I posted is from here: https://github.com/lucasr/picasso/blob/15820945a0dd1f4ca7a76356fb7ad5ff82f8fe80/picasso-sample/src/main/java/com/example/picasso/SampleScrollListener.java – Budius Sep 24 '14 at 13:36
  • so all I'm saying is, maybe who really should have the bounty is @JakeWharton or honestly I do not care that much about it any of it, I just enjoy answering good/interesting questions while my IDE is compiling, so JoeBlow if you can and Bertucci feels so strong about it, I don't mind if change the bounty to him. – Budius Sep 24 '14 at 13:40
  • I don't care too much guys, it's just not cool. I just posted the wrong link of the PR (the link ends */pulls/665 instead of */pulls/666). I edited the wrong link ~20 mins ago, but the reply is from yesterday (check here http://stackoverflow.com/posts/26006215/revisions) way before the edited answer above. That said, PEACE guys ;) Glad I helped somehow – a.bertucci Sep 24 '14 at 13:42
  • Well @Budius probably Lucas Rocha is the man here. He rocked three big features for Picasso in the last few days http://lucasr.org/2014/09/23/new-features-in-picasso/. In his spare time. Respect. – a.bertucci Sep 24 '14 at 13:46
  • indeed.. Lucas Rocha was the man. I just meant that both mine and yours answer was pointing to Picasso pull requests, and that I organically found the same link you wanted to have posted by reading through my original link. When I read the `SampleScrollListener` on Picasso github was the same, that I saw that you miss-typed the link. Anyway, happy coding to all of us. peace-out! – Budius Sep 24 '14 at 13:50
  • Using a context as a tag might not be the best idea as docs mention it http://square.github.io/picasso/javadoc/index.html . I suggest using Activity/Fragment specific constant. like LOG_TAG – defhlt May 27 '15 at 14:07
  • 1
    @mlatu yeah, I've been creating a blank object for those. I'll update the code. – Budius May 28 '15 at 02:33
6

The ability to pause/resume a request will be part of the next release of Picasso 2.4 Just yesterday a pull request containing this feature has been merged in the main branch. It allows to easily define a scroll listener that pauses/resume Picasso while flinging, as shown in the sample code reported below:

public class SampleScrollListener implements AbsListView.OnScrollListener {
  private final Context context;

  public SampleScrollListener(Context context) {
    this.context = context;
  }

  @Override
  public void onScrollStateChanged(AbsListView view, int scrollState) {
    final Picasso picasso = Picasso.with(context);
    if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
      picasso.resumeTag(context);
    } else {
      picasso.pauseTag(context);
    }
  }

  @Override
  public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                       int totalItemCount) {
    // Do nothing.
  }
}
a.bertucci
  • 12,142
  • 2
  • 31
  • 32
  • I read the whole pull request you pointed an can't see anything that is related to the OPs question. It's only a priority queue, nothing related to pause (as you mention) or delay (as OP mention). You can check there https://github.com/square/picasso/pull/666/files , no mention of pause or resume or scroll. Is your link correct? Did you meant to point to the same link I already did? – Budius Sep 24 '14 at 09:05
  • Sorry @Budius, I've pasted the wrong link. The PR I was referring to is this one https://github.com/square/picasso/pull/665. I'm gonna change the answer accordingly. – a.bertucci Sep 24 '14 at 13:04
  • @JoeBlow look at the code, it's pretty self-explanatory: https://github.com/square/picasso/pull/665/files#diff-f11286bbae6959a7a5dd74bf99276f1aR229 – a.bertucci Sep 24 '14 at 13:20
  • dear @Budius, you mat know the answer to this critical question - https://stackoverflow.com/questions/46131941 mfg, – Fattie Sep 09 '17 at 15:05