ピカソを使用して、ビットマップでコールバックを取得します


83

ピカソを使用してアプリの画像をダウンロードしています。

Bitmapロードする前に、最初にアクセスする必要がある状況にありますImageViewDownloader.Responseクラスの存在はこれが可能であることを示唆しているようですが、私は使用例を見つけることができません。ピカソでできるのであれば、この1つの特定のケースを非同期的に処理するためのコードをこれ以上作成したくありません。

誰かが私にそれを行う方法を教えてもらえますか?


回答:


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();
}

投稿では、匿名のコールバックを使用せず、代わりにターゲットにインスタンス変数を使用することを推奨しています。


30
理想的Targetには、ビューまたはビューホルダーオブジェクトに直接実装します。これを行わない場合は、インスタンスへの強力な参照をどこかに維持する必要があります。そうしないと、ガベージコレクションが発生します。
ジェイクウォートン

@JakeWharton:のすべてのアイテムにカスタムアニメーションを適用したい場合は ListView、次のようなことをお勧めしますprivate static ViewHolder { private ImageView imageView; private Target target = new Target() { public void onBitmapLoaded() { // do animation on imageView } } }
mbmc 2014年

@JakeWhartonは、最後のコメントでgithub.com/square/picasso/issues/308で説明しています。
toobsco42 2014

8
onBitmapLoadedはonPrepareLoadの後に最初は呼び出されません
Amit Thaper 2014年

例をありがとう。onDestroyでスーパーコールがないだけです。
ベン・グルート

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); 
        }
});

更新(2016年5月4日):

            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) {

                    }
                });

更新(2016年11月22日)

または、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);
}

Kotlin

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
匿名のターゲットはガベージコレクションされる可能性があります
Steve M

@SteveMそしてそれは何をしますか?リクエストをキャンセルしますか?ビットマップがロードされないようにしますか?
nurettin 2016年

@nurettinピカソ(またはグライド)がターゲットに対してある種の弱い参照を持っていると思います。したがって、匿名の場合、ハードリファレンスはなく、GCに対して脆弱です。ピカソが参照をチェックすると、それはnullになるため、コールバックは呼び出されません。
スティーブM

したがって、GCがコールバックのロードと呼び出しの間に実行され、コールバックが呼び出されないことがあるため、このソリューションは非常に悪いです。
スティーブM

@SteveM私はグーグルプレイでアプリケーションをホストしており、リストビューのスクロール中に常に少なくとも2000人のユーザーがいるアイコンの束をロードし、この方法を使用して一部のアイコンをスケーリングしていますが、苦情はありません、コメント(アイコンが読み込まれないことに関するクラッシュレポートがたくさん表示されます。したがって、少なくとも逸話的には、何らかの理由でガベージコレクションが行われていません。
nurettin 2016年

7

次より簡単なこと:

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

メインスレッドではなくから呼び出す必要があります!

またはRxJava2:

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)

Picassov.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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.