I would have imagined, showing the images from the web would be as simple as setting the correct image source URL to the ImageView. But as it turns out life is not always that simple.
So how do we show the images from the web using the ImageView?
- We have to first download the image using the HttpClient
- Decode the image data using BitmapFactory and convert it into Bitmap
- Associate the Decoded Bitmap with the ImageView
The above code works and works well, it does show the image hosted on the web in the ImageView. However, sometimes, I get an error in the log saying
Now, this is something unexpected. Whenever I get this error the image download stops and image is not shown in the ImageView.
The Cause:
Googled a little and as usual, I was not the only one to face this issue. There are lots of threads online, that mention this particular issue (here and here), "decoder returned false".
It seems that when skip method of the InputStream class does not skip the given number of bytes then, the BitmapFactory fails to decode the InputStream. Usually, the issue occurs on a slow internet connection. However, I cant confirm that, I have a 2Mbps dedicated internet connection, even on this connection issue is reproduicable!
The Fix:
There are two ways of fixing this issue.
Method 1 - Method that involves writing some custom code
This method makes sure that, the skip method of InputStream actually skip's the mentioned number of bytes.
To do this, we will need to wrap the InputStream into a custom class, override the skip method and ensure that we skip the given number of bytes no matter what. This can be achieved by subclassing the FilterInputStream class and overriding the skip method. Lets look at how the new implementation of the skip method.
As seen in the above code, the skip method simply makes sure that we skip the give number of bytes. The class FlushedInputStream now needs to be used while we decode the image. The updated code with the FilteredInputStream looks like
Method 2 - Method that involves using the BufferedInputStream
This method is very simple and straight forward we simply need to wrap the imageContentInputStream with the BufferedInputStream. This also seems to fix the problem. The updated code looks like
Yep, these two methods fix the "decode returned false" issue.