第一次加载时未调用的目标对象

在我的职能中:

public void getPointMarkerFromUrl(final String url, final OnBitmapDescriptorRetrievedListener listener) {
final int maxSize = context.getResources().getDimensionPixelSize(R.dimen.icon_max_size);
Target t = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
if (bitmap != null)
listener.bitmapRetrieved(getBitmapDescriptorInCache(url, bitmap));
else
loadDefaultMarker(listener);
}


@Override
public void onBitmapFailed(Drawable errorDrawable) {
loadDefaultMarker(listener);
}


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


Picasso.with(context)
.load(url)
.resize(maxSize, maxSize)
.into(t);
}

在第一次加载图片时,从不调用 onBitmapLoaded()。我读过一些像 https://github.com/square/picasso/issues/39这样的主题,它建议使用提取(Target t)方法(这似乎是一个弱引用的问题...) ,但是这个函数在毕加索的上一个版本(2.3.2)中不可用。我只有一个 get ()方法,但不能同时使用 into (mytarget)

你能给我解释一下如何用一个定制的 Target 来使用 catch ()吗? 谢谢。

医生: http://square.github.io/picasso/javadoc/com/squareup/picasso/RequestCreator.html#fetch--

44998 次浏览

Picasso 没有对 Target 对象的强引用,因此它被垃圾收集,而 onBitmapLoaded没有被调用。

解决方案非常简单,只需要强有力地参考 Target即可。

public class MyClass {
private Target mTarget = new Target() {...};


public void getPointMarkerFromUrl(final String url, final OnBitmapDescriptorRetrievedListener listener) {


Picasso.with(context)
.load(url)
.resize(maxSize, maxSize)
.into(mTarget);
}
}

正如@lukas 所说(并引用) ,毕加索并没有强烈地引用 Target 对象。若要避免垃圾回收,必须保存对该对象的强引用。

关于 get ()方法。在文档中很清楚的一点是,get ()不能与 ImageView 或 Target 一起使用,它只是用来“预热”缓存,没有其他用途,所以不能按照自己想要的方式使用它。

我建议你像@lukas 解释的那样持有一个强有力的参考文献,它应该会起作用。如果没有,请在该项目的 GitHub 页面上打开一个新的问题。

正如其他受访者(@lukas 和@mradzinski)所指出的,毕加索只保留了对 Target对象的弱引用。虽然你可以在你的类中存储一个强引用 Target,但是如果 Target以任何方式引用 View,这仍然是个问题,因为你也将有效地保持一个强引用 View(这是毕加索明确帮助你避免的事情之一)。

如果你是在这种情况下,我建议将 Target标记为 View:

final ImageView imageView = ... // The view Picasso is loading an image into
final Target target = new Target{...};
imageView.setTag(target);

这种方法的好处是让毕加索为你处理一切。它会为你的每个视图管理 WeakReference对象——一旦不再需要,无论 Target处理什么图像都会被释放,所以你不会因为长期存在的目标而陷入内存泄漏的困境,但是你的 Target 只要它的视图是活的,它就会一直存在。

如果我有 ImageView,我会简单地这样做:

我使用下一个解决方案将位图加载到通知中,所以我只需要位图。

所以创建设置开关将存储目标对象,并删除他们完成加载。

final Set<Target> protectedFromGarbageCollectorTargets = new HashSet<>();


private void loadBitmap(String url) {
Target bitmapTarget = new BitmapTarget();
protectedFromGarbageCollectorTargets.add(bitmapTarget);
Picasso.with(context).load(url).into(bitmapTarget);
}


class BitmapTarget implements Target {


@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
           

//handle bitmap
protectedFromGarbageCollectorTargets.remove(this);
}
}
}


@Override
public void onBitmapFailed(Drawable drawable) {
protectedFromGarbageCollectorTargets.remove(this);
}


@Override
public void onPrepareLoad(Drawable drawable) {
 

}
}
ImageView profile = new ImageView(context);
Picasso.with(context).load(URL).into(profile, new Callback() {
@Override
public void onSuccess() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {//You will get your bitmap here


Bitmap innerBitmap = ((BitmapDrawable) profile.getDrawable()).getBitmap();
}
}, 100);
}


@Override
public void onError() {


}
});

我也遇到过类似的问题,但是保持对目标的引用并没有任何帮助,所以我使用了下面的代码来返回一个位图:


Bitmap bitmap = picasso.with(appContext).load(url).get();

在缺点 -> 没有回调,而且不能在主线程上调用这个函数,必须在 后台线程如下例所示:


handlerThread = new HandlerThread(HANDLER_THREAD_NAME);
handlerThread.start();


Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
@Override
public void run() {
Bitmap bitmap = null;
try {
bitmap = picasso.with(appContext).load(url).get();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bitmap != null) {
//do whatever you wanna do with the picture.
//for me it was using my own cache
imageCaching.cacheImage(imageId, bitmap);
}
}
}
});

另一个更有效的方法就是使用 滑行!

我需要使用他们两个,因为我的项目的目的是使用2个不同的图像下载 api 的显示图片库,并给用户选择使用哪个 api 的能力。

我不得不说,我对结果感到惊讶,格莱德的 api 在各个方面都完美无缺(格莱德的目标没有弱的参考) ,而毕加索给了我地狱(那是我第一次使用格莱德,我通常使用毕加索到目前为止,似乎今天它会改变 ^ ^)。

对于那些不使用视图的用户,以下是解决方案。这个 helper 方法使用一个列表来临时存储目标对象,直到返回结果,这样它就不会被 gc’d:

private List<Target> targets = new ArrayList<>();


public void downloadBitmap(final Context context, final String url, final MyCallback callback) {
Target target = new Target() {


@Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
targets.clear();
callback.onSuccess(bitmap);
}


@Override
public void onBitmapFailed(Exception e, Drawable errorDrawable) {
targets.clear();
callback.onFailure(null);
}


@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
targets.add(target);
Picasso.with(context).load(url).into(target);
}

我曾经遇到过同样的问题,但是当我像下面提到的那样更改依赖项时,它现在可以正常工作了。

 implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.squareup.okhttp:okhttp:2.3.0'
implementation 'com.squareup.okhttp:okhttp-urlconnection:2.3.0'