onBitmapLoaded obiektu docelowego nie wywołanego przy pierwszym ładowaniu

W mojej funkcji:

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

Funkcja onBitmapLoaded () nigdy nie jest wywoływana przy pierwszym ładowaniu zdjęć. Przeczytałem taki temat jak https://github.com/square/picasso/issues/39 które zalecają użycie metody fetch (Target t) (wydaje się, że jest to problem słabego odniesienia...), ale ta funkcja nie jest dostępna w ostatnim wydaniu Picassa (2.3.2). Mam tylko metodę fetch (), ale nie mogę jednocześnie użyć into (mytarget)

Czy mógłbyś mi wyjaśnić jak używać fetch () z Niestandardowy cel ? Dziękuję.

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

 109
Author: psv, 2014-06-12

7 answers

Jak zauważyli inni respondenci (@lukas i @mradzinski), Picasso zachowuje tylko słabe odniesienie do obiektu Target. Chociaż możesz przechowywać silne odniesienie Target w jednej ze swoich klas, to nadal może być problematyczne, jeśli Target odwołuje się do View w jakikolwiek sposób, ponieważ będziesz skutecznie również zachować silne odniesienie do tego View, jak również (co jest jedną z rzeczy, które Picasso wyraźnie pomaga uniknąć).

Jeśli jesteś w tej sytuacji, polecam tagowanie Target do View:

final ImageView imageView = ... // The view Picasso is loading an image into
final Target target = new Target{...};
imageView.setTag(target);
To podejście ma tę zaletę, że pozwala Picasso zająć się wszystkim za Ciebie. Będzie zarządzać obiektami WeakReference dla każdego z Twoich widoków - gdy tylko jeden z nich nie będzie już potrzebny, jakiekolwiek przetwarzanie obrazu zostanie również zwolnione, więc nie utkniesz z wyciekami pamięci z powodu długotrwałych celów, ale cel będzie trwał tak długo, jak jego widok jest żywy.
 219
Author: wrb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-17 17:44:08

Picasso nie posiada mocnego odniesienia do obiektu docelowego, dlatego jest zbierany i nie jest wywoływany onBitmapLoaded.

Rozwiązanie jest ciche proste, wystarczy mocno nawiązać do celu.

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);
   }
}      
 50
Author: lukas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-07 02:31:56

Gdybym miał ImageView, zrobiłbym tak: imageView.setTag (target);

Używam następnego rozwiązania do ładowania bitmap do powiadomień, więc potrzebuję tylko bitmapy.

Więc Utwórz zestaw witch będzie przechowywać obiekty docelowe i usuwać je po zakończeniu ładowania.

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

        }
    }
 18
Author: Flinbor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-06 09:52:31
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() {

            }
        });
 9
Author: Raghav Satyadev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-16 12:47:34

Jak powiedział @ lukas (i cytując), Picasso nie ma mocnego odniesienia do obiektu docelowego. Aby uniknąć zbierania śmieci, musisz posiadać silne odniesienie do obiektu.

O metodzie fetch (). Jest całkiem jasne w dokumentacji, że fetch () nie może być używany z ImageView ani celem, po prostu "rozgrzać" pamięć podręczną i nic więcej, więc nie będziesz mógł jej używać tak, jak chcesz.

Polecam trzymanie mocnych referencji jak @ lukas wyjaśnione, to powinno zadziałać. Jeśli nie, proszę otworzyć nowy numer na stronie GitHub projektu.

 3
Author: mradzinski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-21 03:05:33

Napotkałem podobny problem i trzymanie odniesienia do celu w ogóle nie pomogło, więc użyłem następującego kodu, który zwraca bitmapę:


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

Na dole - > nie ma wywołania zwrotnego i nie możesz wywołać tej funkcji w głównym wątku, musisz uruchomić tę funkcję na wątek tła jak w poniższym przykładzie:


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

Kolejną rzeczą, która działa o wiele lepiej jest po prostu za pomocą Glide!

Musiałem użyć obu z nich, ponieważ celem mojego projektu było użycie 2 różnych API pobierania obrazów, aby pokazać galerię zdjęć i dać użytkownikowi możliwość wyboru, którego api używać.

Muszę powiedzieć, że byłem zdumiony wynikami, API Glide 'a działało bezbłędnie pod każdym względem (cel Glide' a nie ma słabego odniesienia) wile Picasso dał mi piekło (to był mój pierwszy raz przy użyciu Glide ' a, Zwykle używałem Picassa do tej pory, wygląda na to, że dziś to się zmieni ^^).

 3
Author: Roee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 17:40:23

Oto rozwiązanie dla tych, którzy nie używają widoku. Ta metoda pomocnicza używa listy do tymczasowego przechowywania obiektu docelowego, dopóki nie zostanie zwrócony wynik, aby nie był 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);
}
 2
Author: DroidT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-01 21:11:26