How to load low quality and then high quality image afterwards in android (just like WhatsApp profile image)
Asked Answered
F

3

6

I am searching for a design pattern i can use so that in android recyclerView i can load images quickly at low quality and then also make a call to for a high quality image will will write over the low quality image afterwards . I see it often where a low quality image is loaded first and then the high quality appears after.

But How is this done in the adapter for the recycler view. right now i am using picasso for cache and image loading. so for example here is a link to a low quality image:

http://example.com/lowQuality.jpg and likewise high quality http://example.com/highQuality.jpg

So in my adapter for the recyclerView if i do this in the viewholder:

public class SearchItemHolder extends RecyclerView.ViewHolder  {

        @BindView(R.id.iv)
        ImageView iv;

        @BindView(R.id.tv_description)
        TextView tv_description;

        public SearchItemHolder(View view) {
            super(view);
            ButterKnife.bind(this, view);
        }

        public void bindSearch(final SearchModel searchModel) {

            String description = searchModel.getProductName();
            final String imageLowQualityIDUrl = searchModel.getIdLowQualityImage();
            final String imageHighQualityIDUrl = searchModel.getIdHighQualityImage();

            tv_price.setText(price);
            tv_description.setText(description);



            Picasso.with(mContext).load(imageLowQualityIDUrl).into(iv);
//but how to switch it to high quality URL after its finished loading ?


        }
    }

so to be clear, i want that the low quality image can show first as long as the high quality image is not loaded yet.

Update :What i really want is that effect i see on apps where the low quality image loads quickly then after a few seconds it transitions to a higher quality. If there is another tool or way to do this let me know. I want the same effect as the whatsapp profile image (how it fades in from poor quality to good quality).

Fourwheeler answered 27/6, 2017 at 4:21 Comment(6)
Do you mean that there are two versions of images, low quality and high quality then you want to load low quality first and then high quality later?Shannon
Why don't you try and load high quality first, then resize to low quality. If you use this design pattern let's say the two images 45kb and 90kb respectively, if you load once, resize that's 90kb of data, if you load twice the two images that's 135kb.Shannon
What i really want is that effect i see on apps where the low quality image loads quickly then after a few seconds it transitions to a higher qualityFourwheeler
I posted a possible answer please let me know if it works for youShannon
I have got your idea! And I'm interesting with this too. I like the way Flickr's android app do this. Firstly low images are loading in the feed and after some delay, only current visible pictures updates with higher resolution. If you want, we could cooperate in this investigation for better result))Solley
can you check if fresco library has this feature.Fourwheeler
S
8

I found solution with Glide. You can specify low resolution image to be loaded as thumbnail. All you need is:

private void loadImageThumbnailRequest() {  
// setup Glide request without the into() method
DrawableRequestBuilder<String> thumbnailRequest = Glide
    .with( context )
    .load( yourData.getLowQualityLink() );

// pass the request as a a parameter to the thumbnail request
Glide
    .with( context )
    .load( yourData.getHdUrl() )
    .thumbnail( thumbnailRequest )
    .into( imageView );
}

More info in source here

Solley answered 10/7, 2017 at 9:9 Comment(2)
Fresco works much better for eliminating out of memory issues so i like it better. but anyway a question on glide implementation you have here. Does this mean that my server should have a low quality image. so anytime i want to do this effect, my server should have both a high quality and low quality image as Vivee Omomi mentioned. is that right ?Fourwheeler
Yes, your server have to provide images with different quality and different urls. Profit in loading time. With low quality thumbnails your RecyclerView will load images faster and then load hd images "on top" of thumbs. In that case UX will be great. And if you just will "emulate" this behavior, time of loading will increase somehow, because of image resizing. And this will be redundant operation, as I understand you right.Solley
S
1

I think I understand, you want an effect just like WhatsApp profile pic. I think the process depends on your backend, there should be a method in your back end that resizes/compresses the original picture by default and another method that keeps the original size image.

example psuedocode for server

$image = image.jpg

$requestLowQuality = resizeThis($image)

 $requestHighQuality = $image.

So when your app loads the pic in background, the Async task request for $requestLowQuality ..it loads the low quality default version. But when user clicks to view, an Asynctask requests to the server for $requestHighQuality

I think this is how WhatsApp does. That's why you have to wait a while for blurred pictured to become quality.

Picasso will just load the images based on the request methods

Goodluck bro

Shannon answered 27/6, 2017 at 5:57 Comment(2)
exactly how whatsapps profile image does it. your right. but this is more complicated then you wrote i think. because lets say highquality request finish before low quality request. then i need to cancel low quality request etc. there can be timing issuesFourwheeler
You're very right there can be timing issues. But this is only if the server acts on calls immediately. The server must haved prepared these images in storage already, both resized and normal quality, i think this process is good for only single pictures that can be overitten. How about different requests to server using onclick listener and background tasks, you can set a message to make user wait and make these tasks depend on each other. One works while the other waits and vice versaShannon
F
1

i also found out how to do it from Fresco:

Uri lowResUri, highResUri;
DraweeController controller = Fresco.newDraweeControllerBuilder()
    .setLowResImageRequest(ImageRequest.fromUri(lowResUri))
    .setImageRequest(ImageRequest.fromUri(highResUri))
    .setOldController(mSimpleDraweeView.getController())
    .build();
mSimpleDraweeView.setController(controller);

seems to be the same idea as glide. this info is from fresco docs.

Fourwheeler answered 10/7, 2017 at 11:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.