Zingoo is a new promising app that will rock your weekends, outings and any happening that you want to easily enjoy watching its moments over & over again (we are now doing the Android version, then the iOS one). Because we want Zingoo to be born strong, it has to deliver the best possible [UX] to all awesome-moments lovers around the world, which means we have to do our best in loading the images.
Because we (at Begether) do listen to our users, we heard a lot of comments on how WhatsApp is loading images super-fast, so we dug deeper to know what we can do about it, & here is what we find,
What does WhatsApp do?
WhatsApp is doing the following (numbers are approximate):
- Photos sizes range around 100KB, which loads the images pretty fast on most common mobile-network speeds. (part 2 explains how to achieve this)
- Photos are cached, so no need to load them every time you open the app (almost no need to mention this 🙂 ).
- They first show a very small thumbnail (about 10KB or less) until the real image is loaded, & this is the real pro-tip for their better UX.
The last tip has a different variance by calculating the image dimensions & the approximate color of the image that will be shown & applying it to its placeholder, like the coming 3 minutes in this video:
but still, the thumbnail is away more cooler, right? 😉
How is it done?
To achieve the caching there are some good Android libraries out there that are doing a good job, but one of them is doing a way better than the others, which is Picasso. Both caching on disk & on memory are built under the hood, with a very developer-friendly API, I just love what Jake Wharton & his mates did for all of us, thanks guys.
Using Picasso is pretty easy, just like this example one-liner:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
you just need first to add Picasso to your gradle files with the urlConnection library (according to this issue), like this:
compile 'com.squareup.picasso:picasso:2.4.0' compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0'
After solving the caching issue, we need to apply the thumbnail great tip, we need to use Picasso 2 times, one for loading the thumbnail and the other for loading the real image like the comment I made on this issue. Also to avoid the thumbnail’s pixlation effect (due to its small size), it would be better to make a blurring effect on it,
and here is how it is done:
Transformation blurTransformation = new Transformation() { @Override public Bitmap transform(Bitmap source) { Bitmap blurred = Blur.fastblur(LiveImageView.this.context, source, 10); source.recycle(); return blurred; } @Override public String key() { return "blur()"; } }; Picasso.with(context) .load(thumbUrl) // thumbnail url goes here .placeholder(R.drawable.placeholder) .resize(imageViewWidth, imageViewHeight) .transform(blurTransformation) .into(imageView, new Callback() { @Override public void onSuccess() { Picasso.with(context) .load(url) // image url goes here .resize(imageViewWidth, imageViewHeight) .placeholder(imageView.getDrawable()) .into(imageView); } @Override public void onError() { } });
We used the Callback()
functionality to start loading the full image after the thumbnail is completely loaded, with using the blurred thumbnail’s drawable as the new placeholder for the real image, & this is how the magic is being done right here :).
Also the blurring made here is Blur.fastblur()
, thanks to Michael Evans & his EtsyBlurExample example, you can find this class here.
The only remaining part is how to compress the large images (which could be 2 to 4 MB) to be only about 100 KB, which is discussed in Part 2.