Use a thumbnail as a placeholder for Picasso

后端 未结 3 1431
太阳男子
太阳男子 2021-02-02 03:49

From the UX point of view, it will be great to show the user a thumbnail first until the real image completes loading, then showing it to him, but Picasso uses only a resource f

相关标签:
3条回答
  • 2021-02-02 04:11

    You could write a simple helper which calls Picasso twice (as you mentioned).

    I've not tested it, but it should go like

    Picasso.with(context)
            .load(thumbnailUrl)
            .error(errorPlaceholderId)
            .into(imageView, new Callback() {
                            @Override
                            public void onSuccess() {
                                    // TODO Call Picasso once again here
                            }
    
                            @Override
                            public void onError() {                             
                        }
                );
    

    There are a couple of different ways to get your Picasso called twice. One method I could think of (again, not tested) is

    public static void loadImageWithCallback(String url, Callback callback) {
        Picasso.with(context)
            .load(url)
            .error(errorPlaceholderId)
            .into(imageView, callback);
    }
    
    public static void loadImage(String url) {
        Picasso.with(context)
            .load(url)
            .error(errorPlaceholderId)
            .into(imageView);
    }
    
    loadImageWithCallback("http://example.com/mythumbnail.jpg", new Callback() {
    
                        @Override
                        public void onSuccess() {
                            loadImage("http://example.com/myRealImage.jpg");    
                        }
    
                        @Override
                        public void onError() {                             
                    }
    }
    

    Edit: All I know is that Picasso provides this callback mechanism. I'm using it in my app to hide a ProgressBar that is displayed until the image is loaded. I'll hide it in success or error callbacks - so you'll have the option to get notified when image loading is done. Then you can simply call it again. I hope the above approach works.

    0 讨论(0)
  • 2021-02-02 04:34

    Thanks to raveN here & the comments on the original request on github, finally I've got a working solution:

    Picasso.with(context)
           .load(thumb) // thumbnail url goes here
           .into(imageView, new Callback() {
                @Override
                public void onSuccess() {
                    Picasso.with(context)
                            .load(url) // image url goes here
                            .placeholder(imageView.getDrawable())
                            .into(imageView);
                }
                @Override
                public void onError() {
    
                }
            });
    

    The trick here is to get the drawable from the imageView (which is the thumbnail) after the first call & pass it as a placeholder to the second call

    -- update --

    I've made a blog post describing the whole scenario

    0 讨论(0)
  • 2021-02-02 04:34

    I originally used AbdelHady's solution but found that the larger image is only loaded after the thumbnail is done loading so I came up with this instead.

    Assuming you have a utility class in your project;

    public final class U {
    
    public static void picassoCombo(final RequestCreator thumbnail,
                                    final RequestCreator large,
                                    final ImageView imageView) {
        Target target = new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                imageView.setImageBitmap(bitmap);
            }
    
            @Override
            public void onBitmapFailed(Drawable errorDrawable) {
                imageView.setImageDrawable(errorDrawable);
            }
    
            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {
                thumbnail.into(imageView);
            }
        };
    
        imageView.setTag(target); // To prevent target from being garbage collected
        large.into(target);
    }
    }
    

    Usage:

    U.picassoCombo(
            Picasso.with(context)
                    .load("http://lorempixel.com/200/100/sports/1/")
                    .placeholder(R.drawable.ic_image_placeholder),
            Picasso.with(context)
                    .load("http://lorempixel.com/800/400/sports/1/")
                    .error(R.drawable.ic_image_broken),
            imageView
    );
    

    In the above example the placeholder is set first, the thumbnail url is set next, and regardless of whether the thumbnail request is done, successful, or failed, the large image request is set once it is done. If the large image request failed, then the error drawable is set.

    The only issue is that if you use setIndicatorsEnabled(true) the debug indicators don't show for the large request. As far as I can tell this seems to be by design according to this issue convo

    0 讨论(0)
提交回复
热议问题