Может очереди Пикассо для меня?
вот критический момент, который я не знаю относительно поведения Пикассо.
представьте, что вы, скажем, показываете слайд-шоу из десяти элементов. Скажем, они на экране по десять секунд.
идеальным поведением было бы следующее: В начале слайд-шоу Я просто выполняю следующее:
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 )
и, на самом деле, Пикассо сделал бы это по одному, в очереди.
каково поведение Пикассо, Если я скажу ему предварительно согреться 10 адресов сразу?
возможно ли, чтобы Пикассо делал вещи только по одному за раз, по порядку - есть ли такой вариант?
(другие возникающие вопросы: можете ли вы отменить очередь или ...?)
фреска
благодаря удивительному ответу @alicanozkara на этой странице Я впервые узнал о
https://github.com/facebook/fresco
(13k звезд) к лучшему или худшему я думаю, что Пикассо эра, вероятно, закончилась.
4 ответов
используя только Picasso
, Я думаю, что вы можете достичь, это:
1) загрузить все изображения асинхронно в кэше с помощью fetch()
вот так:
Picasso.with(context).load(URL).fetch();
вы также можете добавить приоритет для изображений, которые вы хотите загрузить раньше: (возможно, упомянуть высокий приоритет для первых нескольких изображений слайда)
Picasso.with(context)
.load(URL)
.priority(Picasso.Priority.HIGH) // Default priority is medium
.fetch();
2) об отмене очереди, вы можете добавить общие tag()
к вашим изображениям и вы можете пауза / отмена / возобновление в любое время!
private static final Object TAG_OBJECT = Object();
Picasso.with(context)
.load(URL)
.tag(TAG_OBJECT)
// can be any Java object, must be the same object for all requests you want to control together.
тогда мы можем управлять тегом так:
Picasso.with(context)
.pauseTag(TAG_OBJECT)
//.resumeTag(TAG_OBJECT)
//.cancelTag(TAG_OBJECT)
3) еще одна важная вещь, которую я хотел бы предложить, - это когда вы предварительно загружаете свои изображения, только сохраняете их в свой дисковый кэш и загружаете их в свой кэш памяти только во время отображения. Это предотвратит промывку других важных изображений из кэша памяти:
Picasso
.with(context)
.load(URL)
.memoryPolicy(MemoryPolicy.NO_STORE) //Skips storing the final result into memory cache.
.fetch()
4) для последовательной загрузки изображений в очереди, вы можете пройти свой собственный ExecutorService
(SingleThreadExecutor
в вашем случае) с помощью executor(ExecutorService)
способ, присутствующий в Picasso.Builder
вы даже можете изменить размер кэша диска с помощью downloader(Downloader)
способ и кэш-памяти с помощью memoryCache(Cache)
метод, как нашли в Picasso.Builder
класса.
Другие Удивительные Библиотеки:
возможно ли, чтобы Пикассо делал вещи только по одному за раз, по порядку - есть ли такой вариант?
Я не уверен, что это можно сделать с самим Пикассо, но, по крайней мере, RxJava может быть применима к этой проблеме.
я опубликую фрагмент кода с комментариями:
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()
));
}
}
это будет вывод в logcat:
Это идеальный сценарий, когда каждое изображение получает успешно загружен. Этот фрагмент не обрабатывает случай, когда одно из изображений не может быть загружено. Как только Пикассо не сможет загрузить один из них - поток будет прерван и onError()
будет называться.
В Пикассо.Builder вы можете дать конкретный ExecutorService: https://square.github.io/picasso/2.x/picasso/com/squareup/picasso/Picasso.Builder.html#executor-java.util.concurrent.ExecutorService-
Если вы даете новый исполнитель одного потока, https://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor(), Picasso будет загружать все ваши изображения по одному за раз.
нет исправления с одним методом вызова для цепочки с Пикассо, но вы можете создать помощника следующим образом:
public PicassoSlideshow {
private static PicassoSlideshow instance;
private WeakReference<ImageView> view;
private Handler handler;
private int index;
private String[] urls;
private long delay;
private PicassoSlideshow() {
//nothing
}
public static PicassoSlideshow with(ImageView view) {
if (instance == null) {
instance = new PicassoSlideshow();
}
instance.setView(view);
}
private void setView(ImageView view) {
this.view = new WeakReference<>(view);
}
//Note: I'm only suggesting varargs because that's what you seem to have in the question
public void startSlideshow(long interval, String... urls) {
if (handler == null) {
handler = new Handler();
}
index = 0;
this.urls = urls;
delay = interval;
displayNextSlide();
}
private void displayNextSlide() {
//display one
ImageView iv = view.get();
if (iv != null) {
Picasso.with(iv.getContext())
.load(urls[index]).into(iv);
index++;
if (index < urls.length) {
//preload next
Picasso.with(iv.getContext()).fetch(urls[index]);
//on timer switch images
handler.postDelayed(PicassoSlideshow::displayNextSlide, delay);
}
}
}
}
использование:
PicassoSlideshow.with(view).startSlideshow(10000, url1, url2, url3, url9);
обратите внимание, я только что написал это с верхней части головы, в то время как моя IDE аннулирует свои кэши, поэтому вам может потребоваться немного настроить его