onBitmapLoaded целевого объекта не вызывается при первой загрузке
в :
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 который рекомендует использовать метод fetch (Target t) (похоже, это проблема слабой ссылки...), но эта функция недоступна в последнем выпуске picasso (2.3.2). У меня есть только метод fetch (), но я не могу использовать в(mytarget) одновременно
не могли бы вы объяснить мне как использовать fetch () с пользовательской целью, пожалуйста ? Спасибо.
Doc : http://square.github.io/picasso/javadoc/com/squareup/picasso/RequestCreator.html#fetch--
7 ответов:
Picasso не содержит сильной ссылки на целевой объект, поэтому он собирается мусор и onBitmapLoaded не вызывается.
решение тихое простое, просто сделайте сильную ссылку на цель.
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); } }
Если бы у меня был ImageView, я бы просто сделал так: imageView.setTag (target);
Я использую следующее решение для загрузки растровых изображений в уведомления, поэтому мне нужен только рисунок.
Так что создать набор ведьма будет хранить целевые объекты и удалить их по завершении загрузки.
final Set<Target> protectedFromGarbageCollectorTargets = new HashSet<>(); private void loadBitmap(String url) { Target bitmapTarget = new BitmapTarget(nEvent); 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() { } });
Как сказал @lukas (и цитируя), Пикассо не имеет сильной ссылки на целевой объект. Чтобы избежать сборки мусора вы должны иметь сильную ссылку на объект.
о методе fetch (). В документации довольно ясно, что fetch() не должен использоваться с ImageView или целью, это просто "разогреть" кэш и ничего больше, поэтому вы не сможете использовать его так, как хотите.
Я рекомендую вам держать сильную ссылку, как @lukas объяснил, что это должно работать. Если нет, пожалуйста, откройте новый вопрос на GitHub странице проекта.
я столкнулся с подобной проблемой и удержание ссылки на цель не помогло вообще, поэтому я использовал следующий код, который возвращает растровое изображение:
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 Glide работал безупречно во всех аспектах (цель Glide не имеет слабой ссылки) wile Picasso дал мне ад (это был мой первый раз, когда я использовал Glide, я обычно использовал Picasso до сих пор, похоже, сегодня это изменится ^^ ).
вот решение для тех, кто не с помощью зрения. Этот вспомогательный метод использует список для временного хранения целевого объекта до тех пор, пока результат не будет возвращен, чтобы он не был 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(Drawable errorDrawable) { targets.clear(); callback.onFailure(null); } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { } }; targets.add(target); Picasso.with(context).load(url).into(target); }