Here's a critical point I don't know concerning the behavior of Picasso.
Imagine you are, say, showing a slide-show of ten items. Say, they are on-screen for ten seconds each.
The ideal behavior would be this: at the start of the slide show, I simply perform following:
picasso.get( url1 )
picasso.get( url2 )
picasso.get( url3 )
picasso.get( url4 )
picasso.get( url5 )
picasso.get( url6 )
picasso.get( url7 )
picasso.get( url8 )
picasso.get( url9 )
picasso.get( url10 )
And, in fact, Picasso would do those one at a time, in a queue.
What is the behavior of Picasso, if I tell it to pre-warm 10 urls all at once?
Is it possible to have Picasso do things only one at a time, in order - is there such an option?
(Other questions arising are, can you cancel the queue, or ...?)
thanks to an amazing answer @alicanozkara on this page I learned for the first time about
https://github.com/facebook/fresco
(13k stars) for better or worse I think the Picasso era is probably over.
Glide's loading times are faster and it uses a small amount of memory for cache, but the library size is quite large. It, too, is easy to implement. Glide might be a better alternative to Picasso when memory footprint is less of a concern or more and larger images need to be processed.
Is it possible to have Picasso do things only one at a time, in order - is there such an option?
I am not sure it can be done with Picasso itself, but at least RxJava may be applicable to this problem.
I'll post a snippet of code with comments:
public class MainActivity extends AppCompatActivity {
public static final List<String> urlList = Arrays.asList(
"http://i.imgur.com/UZFOMzL.jpg",
"http://i.imgur.com/H981AN7.jpg",
"http://i.imgur.com/nwhnRsZ.jpg",
"http://i.imgur.com/MU2dD8E.jpg"
);
List<Target> targetList = new ArrayList<>();
List<Completable> completables = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final long start = System.currentTimeMillis();
// emit each url separately
Observable.fromIterable(urlList)
// flatmap to an Observable<Completable>
.flatMap(url ->
// fromCallable ensures that this stream will emit value as soon as it is subscribed
// Contrary to this, Observable.just() would emit immediately, which we do not want
Observable.fromCallable(() ->
// We need to know whether either download is
// completed or no, thus we need a Completable
Completable.create(e -> {
Target target = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Log.i("vvv", "downloaded " + url + ", " + (System.currentTimeMillis() - start));
e.onComplete();
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
e.onError(new IllegalArgumentException("error happened"));
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
// need to keep a strong reference to Target, because Picasso holds weak reference
targetList.add(target);
Picasso.with(MainActivity.this)
.load(url)
.into(target);
})))
// collecting all Completables into a list
.collectInto(completables, List::add)
// flatmap-ing this Observable into a Completable, concatenating each completable
// to next, thus they will be downloaded in order
.flatMapCompletable(Completable::concat)
// clearing the strong reference we retained earlier
.doFinally(() -> {
targetList.clear();
targetList = null;
})
.subscribe(
() -> Log.i("vvv", "done: " + (System.currentTimeMillis() - start)),
throwable -> Log.e("vvv", "err " + throwable.getMessage()
));
}
}
This will be the output in logcat:
This is the ideal case scenario, when each image gets successfully loaded. This snippet doesn't handle the case, when one of images cannot be loaded. As soon as Picasso fails to load one of them - the stream will be interrupted and onError()
would be called.
In Picasso.Builder you can give a specific ExecutorService: https://square.github.io/picasso/2.x/picasso/com/squareup/picasso/Picasso.Builder.html#executor-java.util.concurrent.ExecutorService-
If you give a new single thread executor, https://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor(), Picasso will download all your images one at a time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With