Використовуйте Пікассо, щоб отримати зворотний дзвінок за допомогою растрової карти


83

Я використовую Пікассо для завантаження зображень для мого додатка.

Я Bitmapпотрапив у ситуацію, коли мені потрібно отримати доступ до першого, перш ніж його завантажити в ImageView. Присутність Downloader.Responseкласу, здається, говорить про те, що це можливо, але я не можу знайти прикладів використання. Я не хочу писати ще купу коду для асинхронної обробки цього конкретного випадку, якщо це можливо зробити з Пікассо.

Хто-небудь може показати мені, як це зробити?


Відповіді:


172

Знайшов відповідь на github на випадок, якщо хтось цікавиться:

private Target target = new Target() {
      @Override
      public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
      }

      @Override
      public void onBitmapFailed(Drawable errorDrawable) {
      }

      @Override
      public void onPrepareLoad(Drawable placeHolderDrawable) {
      }
}

private void someMethod() {
   Picasso.with(this).load("url").into(target);
}

@Override 
public void onDestroy() {  // could be in onPause or onStop
   Picasso.with(this).cancelRequest(target);
   super.onDestroy();
}

Пост рекомендує не використовувати анонімний зворотний виклик, а замість цього використовувати змінну екземпляра для target.


30
В ідеалі ви б реалізували Targetна поданні або об'єкті власника перегляду безпосередньо. Якщо ви цього не робите, вам потрібно зберегти чітке посилання на екземпляр десь, інакше він буде збирати сміття.
Джейк Уортон,

@JakeWharton: якщо я хочу застосувати власну анімацію до кожного елемента a ListView, ви пропонуєте зробити щось на зразок private static ViewHolder { private ImageView imageView; private Target target = new Target() { public void onBitmapLoaded() { // do animation on imageView } } }:?
mbmc

@JakeWharton пояснює це тут github.com/square/picasso/issues/308 в останньому коментарі.
toobsco42

8
onBitmapLoaded не дзвонить вперше після onPrepareLoad
Amit Thaper

Дякую за приклад. Мені не вистачає супер дзвінка в onDestroy.
Ben Groot

68

взято звідси :

Picasso.with(this)
    .load(url)
    .into(new Target() {
        @Override
        public void onBitmapLoaded (final Bitmap bitmap, Picasso.LoadedFrom from){
            /* Save the bitmap or do something with it here */

            //Set it in the ImageView
            theView.setImageBitmap(bitmap); 
        }
});

Оновлено (04 травня 2016 р.):

            Picasso.with(this)
                .load(youUrl)
                .into(new Target() {
                    @Override
                    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

                    }

                    @Override
                    public void onBitmapFailed(Drawable errorDrawable) {

                    }

                    @Override
                    public void onPrepareLoad(Drawable placeHolderDrawable) {

                    }
                });

Оновлено (22 листопада 2016 р.)

або використовуючи надійну довідку для Targetтого, щоб це не було зібраним сміттям

Target target = new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {

            }

            @Override
            public void onBitmapFailed(Drawable errorDrawable) {

            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {

            }
        };


void foo() {
        Picasso.with(getContext()).load(getUrl()).into(target);
}

Котлін

object: com.squareup.picasso.Target {
                  override fun onBitmapFailed(e: java.lang.Exception?, errorDrawable: Drawable?) {
                    TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
                }

                  override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
                    TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
                  }

                  override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {

                  }
                }

6
анонімний Ціль може бути зібраним сміттям
Стів М

@SteveM А що це робити? Скасувати запит? Запобігти завантаженню растрового зображення?
нуреттин

@nurettin Я припускаю, що Пікассо (або Glide) має якесь слабке посилання на ціль. Отже, якщо це анонімне посилання, то твердих посилань немає, і воно вразливе для GC. Коли Пікассо перевіряє посилання, воно буде нульовим, тому зворотний виклик не буде викликаний.
Стів М

Отже, це рішення насправді погане, оскільки GC іноді може запускатись між завантаженням та викликом зворотного виклику та спричиняти не викликання зворотного виклику.
Стів М

@SteveM Я розміщую програму в Google Play, яка завантажує купу значків під час прокрутки списку переглядів щонайменше з 2000 користувачами в будь-якому випадку, масштабуючи деякі піктограми за допомогою цього методу, але скарг, коментарів я не бачив ( Я отримую багато) або звіт про аварійне завершення роботи з іконками, які не завантажуються. Тож, принаймні анекдотично, це не збирання сміття з якихось причин.
нуреттин

7

Що може бути легше, ніж наступне:

val url: String = "https://...."
val bitmap: Bitmap = Picasso.with(context).load(url).get()

Викликати слід не з головної нитки!

або з RxJava 2:

fun getBitmapSingle(picasso: Picasso, url: String): Single<Bitmap> = Single.create {
    try {
        if (!it.isDisposed) {
            val bitmap: Bitmap = picasso.load(url).get()
            it.onSuccess(bitmap)
        }
    } catch (e: Throwable) {
        it.onError(e)
    }
}

Отримати растрове зображення:

getBitmapSingle(Picasso.with(context), "https:/...")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ bitmap ->
                // val drawable = BitmapDrawable(context, bitmap)
                }, Throwable::printStackTrace)

Я використовував Picasso v.2.5.2


2

Я думав, можливо, комусь із вас сподобається версія RxJava наведеної вище відповіді ... Ось вона:

    public static Observable<Bitmap> loadBitmap(Picasso picasso, String imageUrl) {
    return Observable.create(new Observable.OnSubscribe<Bitmap>() {
        @Override
        public void call(Subscriber<? super Bitmap> subscriber) {
            Target target = new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    subscriber.onNext(bitmap);
                    subscriber.onCompleted();
                }

                @Override
                public void onBitmapFailed(Drawable errorDrawable) {
                    subscriber.onError(new Exception("failed to load " + imageUrl));
                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                }
            };
            subscriber.add(new Subscription() {
                private boolean unSubscribed;

                @Override
                public void unsubscribe() {
                    picasso.cancelRequest(target);
                    unSubscribed = true;
                }

                @Override
                public boolean isUnsubscribed() {
                    return unSubscribed;
                }
            });
            picasso.load(imageUrl).into(target);
        }
    });
}

PS Підписуючись, зберігайте посилання на підписку у своїй діяльності, інакше цільовий показ буде GC, перш ніж ви отримаєте відповідь ...


Здається, цей код зараз не працює з останньою версією RxAndroid
Pavandroid
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.