0

I made a target of Picasso in a for loop. The first time I receive 1 image and the other images going into the 'onPrepareLoad' statement. The second time I receive all images. Why is it not working the first time?

Code:

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

        for (int i = 0; i < alleFotosArray.size(); i++) {
            final Target target = new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    protectedFromGarbageCollectorTargets.remove(this);

                    int width = bitmap.getWidth();
                    int height = bitmap.getHeight();

                    deelnemerSizesFotos sizeFotos = new deelnemerSizesFotos();

                    sizeFotos.setWidth(width);
                    sizeFotos.setHeight(height);

                    sizeFotosArray.add(sizeFotos);
                }

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

                    deelnemerSizesFotos sizeFotos = new deelnemerSizesFotos();

                    sizeFotos.setWidth(200);
                    sizeFotos.setHeight(200);

                    sizeFotosArray.add(sizeFotos);
                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                    deelnemerSizesFotos sizeFotos = new deelnemerSizesFotos();

                    sizeFotos.setWidth(200);
                    sizeFotos.setHeight(200);

                    sizeFotosArray.add(sizeFotos);
                }
            };

            protectedFromGarbageCollectorTargets.add(target);
            Picasso.with(c).load(alleFotosArray.get(i).getImageurl()).into(target);
}
sander
  • 21
  • 5
  • Possible duplicate of [onBitmapLoaded of Target object not called on first load](http://stackoverflow.com/questions/24180805/onbitmaploaded-of-target-object-not-called-on-first-load) – HendraWD Dec 08 '16 at 14:53
  • I have final Target, but how can I do this with an ImageView? I don't have an ImageView. – sander Dec 08 '16 at 15:01
  • `final` **will not** prevent from garbage collection. You need to keep the reference of the `Target` to an object that will not garbage collected. Just an idea, you can make a member variable `List targetList = new ArrayList<>();` to your `Activity` to keep the references of the targets there by calling `targetList.add(target);`. – HendraWD Dec 08 '16 at 15:05
  • Where do I need to put 'targetList.add(target)'? – sander Dec 08 '16 at 15:11
  • Inside your for loop. Let me know if this resolve the problem or not. – HendraWD Dec 08 '16 at 15:13
  • I did it below Picasso load – sander Dec 08 '16 at 15:15
  • I'm not sure what to do. – sander Dec 08 '16 at 15:15
  • Put it before you call Picasso.with(c).load... and re-run your application and see if it resolve the problem – HendraWD Dec 08 '16 at 15:17
  • I updated my question so you can see what I did. I tried with target list but still same problem. – sander Dec 08 '16 at 15:27
  • see my answer below – HendraWD Dec 08 '16 at 15:28

3 Answers3

0

Add Memory Policy to Picasso

Picasso.with(c).load(alleFotosArray.get(i).getImageurl()).memoryPolicy(MemoryPolicy.NO_CACHE).into(target);
Tabish Hussain
  • 852
  • 5
  • 13
0

You just need to keep a references to the target objects you created, because Picasso use WeakReference to it and since Android 2.3 (API Level 9), garbage collector is more aggressive with collecting soft/weak references.

Example of keeping references within an Activity

public class YourActivity extends Activity {

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getImages();
    }

    private void getImages() {
        for (int i = 0; i < alleFotosArray.size(); i++) {
            final Target target = new Target() {
                @Override
                public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    int width = bitmap.getWidth();
                    int height = bitmap.getHeight();

                    deelnemerSizesFotos sizeFotos = new deelnemerSizesFotos();

                    sizeFotos.setWidth(width);
                    sizeFotos.setHeight(height);

                    sizeFotosArray.add(sizeFotos);
                }

                @Override
                public void onBitmapFailed(Drawable errorDrawable) {
                    deelnemerSizesFotos sizeFotos = new deelnemerSizesFotos();

                    sizeFotos.setWidth(200);
                    sizeFotos.setHeight(200);

                    sizeFotosArray.add(sizeFotos);
                }

                @Override
                public void onPrepareLoad(Drawable placeHolderDrawable) {
                    deelnemerSizesFotos sizeFotos = new deelnemerSizesFotos();

                    sizeFotos.setWidth(200);
                    sizeFotos.setHeight(200);

                    sizeFotosArray.add(sizeFotos);
                }
            };

            targetList.add(target);
            Picasso.with(c).load(alleFotosArray.get(i).getImageurl()).into(target);
        }
    }
}
HendraWD
  • 2,984
  • 2
  • 31
  • 45
  • I use an AsyncTask class but a List doesn't work also. – sander Dec 08 '16 at 15:29
  • Have you declared your list as a member variable? – HendraWD Dec 08 '16 at 15:31
  • In my question you can see how I did it. I wrote my List in the global variable list. – sander Dec 08 '16 at 15:32
  • But it's really weird that the second time it does work and the first time not (probably because they're already in cache). – sander Dec 08 '16 at 15:37
  • That is weird if you already stored the references on global variable list, and the behavior still exist. Usually that should worked... – HendraWD Dec 08 '16 at 15:47
  • I'm seriously 4 days working on this shit... One time I tried: 'BitmapFactory.decodeStream(url.openConnection().getInputStr‌​eam()' and that worked, but then I added an image with "(1)" at the end of the name of the image and at that time it crashed. I also tried Glide and that didn't work also. – sander Dec 08 '16 at 15:51
  • I don't know if I did it right as how he said it, but it doesn't work. – sander Dec 08 '16 at 15:57
  • Is it a problem when you load those images in the 'onPostExecute'? – sander Dec 08 '16 at 16:17
  • Maybe it is better if you show your whole code. There is no problem where you called Picasso, since it has it's own thread. – HendraWD Dec 08 '16 at 16:56
  • Tomorrow 09:15 AM I will add my code. I don't have the time for it at the moment. – sander Dec 08 '16 at 17:42
  • In the morning I was thinking about it and in a few seconds I had something in my head so I tested it and damnn it works... – sander Dec 09 '16 at 08:36
  • Then you can post your solution here, so others that have the same problem can learn from you – HendraWD Dec 09 '16 at 09:07
  • Oke, I will post it immediately. – sander Dec 09 '16 at 09:08
  • Can you like my answer... :))) – sander Dec 09 '16 at 09:15
0

I'm using a ViewPager, so I don't have to load all images immediately. If I want I can load them 1 by 1 in the 'onPageSelected' method of the ViewPager.

Code:

AndroidImageAdapter adapterView = new AndroidImageAdapter(c, alleFotosArray, left, right, flImage);
        mViewPager.setAdapter(adapterView);

        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                    Picasso.with(c).load(alleFotosArray.get(position).getImageurl()).into(new Target() {
                        @Override
                        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                            int width = bitmap.getWidth();
                            int height = bitmap.getHeight();

                            deelnemerSizesFotos sizeFotos = new deelnemerSizesFotos();

                            sizeFotos.setWidth(width);
                            sizeFotos.setHeight(height);

                            sizeFotosArray.add(sizeFotos);

                            try {
                                int widthFoto = bitmap.getWidth();
                                int heightFoto = bitmap.getHeight();

                                heightContainer = mViewPager.getHeight();
                                widthContainer = mViewPager.getWidth();

                                if (widthFoto == 0 || heightFoto == 0) {
                                    widthFoto = 200;
                                    heightFoto = 200;
                                }

                                    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) flImage.getLayoutParams();

                                    //in het begin krijg je 1 foto te zien van de vorige pagina. Omdat ik de breedte en hoogte niet van de container krijg
                                    //heb ik deze if gemaakt waarbij de hoogte en breedte wordt opgehaald
                                    if (heightContainer == 0 || widthContainer == 0) {
                                        heightContainer = params.height;

                                        //breedte scherm pixels ophalen
                                        DisplayMetrics metrics = new DisplayMetrics();
                                        WindowManager windowManager = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
                                        windowManager.getDefaultDisplay().getMetrics(metrics);

                                        widthContainer = metrics.widthPixels;
                                    }

                                    float r = (float) widthFoto / (float) widthContainer;
                                    float h = (float) heightFoto / r;

                                    // Changes the height and width to the specified *pixels*
                                    params.height = (int) h;
                                    params.width = widthContainer;

                                    flImage.setLayoutParams(params);
                            } catch (Exception e) {
                                FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) flImage.getLayoutParams();

                                //breedte scherm pixels ophalen
                                DisplayMetrics metrics = new DisplayMetrics();
                                WindowManager windowManager = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
                                windowManager.getDefaultDisplay().getMetrics(metrics);

                                params.width = metrics.widthPixels;

                                flImage.setLayoutParams(params);
                            } 

                        @Override
                        public void onBitmapFailed(Drawable errorDrawable) {
                            deelnemerSizesFotos sizeFotos = new deelnemerSizesFotos();

                            sizeFotos.setWidth(200);
                            sizeFotos.setHeight(200);

                            sizeFotosArray.add(sizeFotos);
                        }

                        @Override
                        public void onPrepareLoad(Drawable placeHolderDrawable) {
                            deelnemerSizesFotos sizeFotos = new deelnemerSizesFotos();

                            sizeFotos.setWidth(200);
                            sizeFotos.setHeight(200);

                            sizeFotosArray.add(sizeFotos);
                        }
                    });
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
sander
  • 21
  • 5