One important feature in most mobile store apps is the ability to show images of products (or services). In most cases, it's not possible to store all those images on the mobile device. It could be because products are added or removed, that the images change over time, or that they would simple take up to much space in the device's memory (or even on a storage card).
A possible solution to these problems would be to get the images on demand over the network. But even if the image size was kept to a minimum, most wireless connections (especially if you are out of 3G coverage) wouldn't be able to deliver the images fast enough to create a responsive user experience. The solution could be to show a temporary image at once, load the images on background threads, and replace the temporary image when the downloads is complete. That is what I will show you how to do here.
When the image is first shown, which could be in the list or detail dialog, code similar to the following is run:
if(this.image == null)
{
this.image = Common.Values.LoadBitmap("dummy.jpg", 70, 52);
Thread loadImageThread = new Thread(new ThreadStart(loadImage));
loadImageThread.Start();
loadingImage = true;
}
If the image is not set, it's the first time this image is to be shown, we start by loading a dummy image while the real image is loading. Then we start a background thread to load the image, and it's code look like this:
private void loadImage()
{
Bitmap image = Common.Values.LoadBitmap(
new Uri(Common.Values.ImageUrl + car.ImageFileName), 70, 52);
lock(this.image)
this.image = image;
loadingImage = false;
}
The download of the image is started, and when it's done, the image is set and the background thread ends. The actual loading of the image from an URL looks like this:
public Bitmap LoadBitmap(Uri uri, int width, int height)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Bitmap image = LoadBitmap(resp.GetResponseStream(), width, height);
resp.GetResponseStream().Close();
return image;
}
Just a simple web request with the resulting stream directly used to create a bitmap image.
While the image is loading, the Paint event will do something similar to the following:
lock(this.image)
g.DrawImage(image, position.Left, position.Top);
if(loadingImage)
g.DrawString("Loading...", SmallFont, FontBrush,
position.Left + 4, position.Top + 2);
The locking of the image variable is necessary to avoid thread concurrency problems, and we are also adding a text to the dummy image while the real one is loading.
This simple technique can be used in many situations to increase the user experience.