使用 Picasso 获取带有位图的回调
Posted
技术标签:
【中文标题】使用 Picasso 获取带有位图的回调【英文标题】:Use Picasso to get a callback with a Bitmap 【发布时间】:2013-12-09 11:53:32 【问题描述】:我正在使用 Picasso 为我的应用下载图像。
我需要先访问Bitmap
,然后才能将其加载到ImageView
。 Downloader.Response
类的存在似乎表明这是可能的,但我找不到任何使用示例。如果可以使用毕加索,我不想编写更多代码来异步处理这个特殊情况。
谁能告诉我怎么做?
【问题讨论】:
***.com/a/36310327/5028508 【参考方案1】:如果有人想知道,请在 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
。如果您不这样做,则需要在某处维护对实例的强引用,否则它将被垃圾收集。
@JakeWharton:如果我想在ListView
的每个项目上应用自定义动画,你建议这样做:private static ViewHolder private ImageView imageView; private Target target = new Target() public void onBitmapLoaded() // do animation on imageView
?
@JakeWharton 在最后一条评论中在这里github.com/square/picasso/issues/308 解释。
onBitmapLoaded onPrepareLoad 后第一次不调用
感谢您的示例。我只是错过了 onDestroy 中的一个超级调用。【参考方案2】:
取自here:
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);
科特林
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?)
【讨论】:
匿名目标可能被垃圾回收 @SteveM 那会做什么?取消请求?防止加载位图? @nurettin 我假设毕加索(或 Glide)对目标有某种弱引用。因此,如果它是匿名的,则没有硬引用,并且容易受到 GC 的攻击。当 Picasso 检查引用时,它将为 null,因此不会调用回调。 所以这个解决方案真的很糟糕,因为GC可能偶尔会在回调的加载和调用之间运行,导致回调不被调用。 @SteveM 我在 google play 上托管了一个应用程序,该应用程序在其列表视图滚动期间加载一堆图标,在任何情况下至少有 2000 个用户,使用这种方法缩放一些图标,但我没有没有看到任何关于图标未加载的投诉、评论(我收到很多)或崩溃报告。所以至少有趣的是,由于某种原因,它没有收集垃圾。【参考方案3】:比下一个更容易:
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
【讨论】:
【参考方案4】:我想也许你们中的一些人想要上述答案的 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);
);
附:订阅时,将订阅引用存储在您的活动中,否则,目标将在您收到响应之前被 GC...
【讨论】:
似乎这段代码现在不适用于最新的 RxAndroid以上是关于使用 Picasso 获取带有位图的回调的主要内容,如果未能解决你的问题,请参考以下文章
在 AsyncTask 中使用 Picasso 从 URL 获取位图