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 109

7 ответов:

как отмечают другие респонденты (@lukas и @mradzinski), Пикассо только держит слабую ссылку на

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