SharpAffair
SharpAffair

Reputation: 5488

MonoDroid Download Image to ImageView

I'm just starting experimenting with MonoDroid using Visual Studio.

Trying to download image from the web and display it in an ImageView control.

Unfortunately, some strange reason prevents the image from being displayed in the ImageView. Although the image appears to be downloaded successfully, the control remains blank.

Anything I'm doing wrong here?

The code is as follows:

private void DoClick(object sender, EventArgs e)
{

    WebClient web = new WebClient();
    web.DownloadDataCompleted += new DownloadDataCompletedEventHandler(web_DownloadDataCompleted);
    web.DownloadDataAsync(new Uri(@"http://upload.wikimedia.org/wikipedia/commons/d/d9/Test.png"));


    Toast.MakeText(this, "Image downloaded!", ToastLength.Short).Show();
}


void web_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{

    if (e.Error != null)
    {
        Toast.MakeText(this, e.Error.Message, ToastLength.Short).Show();
    }

    else
    {

        Bitmap bm = BitmapFactory.DecodeByteArray(e.Result, 0, e.Result.Length);

        ImageView imgView = FindViewById<ImageView>(Resource.Id.MyImageView);
        imgView.SetImageBitmap(bm);


    }


}

With the Main.axml defined as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<Button  
    android:id="@+id/MyButton"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/Hello"
    />


  <ImageView
    android:id="@+id/MyImageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_below="@+id/MyButton"/>



</LinearLayout>

Upvotes: 1

Views: 2927

Answers (1)

Greg Shackles
Greg Shackles

Reputation: 10139

There are two problems I see here:

  1. Your "image downloaded" toast will be called immediately after you start the download since the download is asynchronous. You should place it in the web_DownloadDataCompleted method if you want it to show once the download completes.
  2. The main problem here is that you're trying to update the UI from a background thread. Since the download is asynchronous it is processed on a background thread, including your callback. However, you cannot make updates to the UI from a background thread. If you wrap the contents of that method in a call to RunOnUiThread(), the code works as expected:

    void web_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
    {
    
        if (e.Error != null)
        {
            RunOnUiThread(() =>
                Toast.MakeText(this, e.Error.Message, ToastLength.Short).Show());
        }
        else
        {
    
            Bitmap bm = BitmapFactory.DecodeByteArray(e.Result, 0, e.Result.Length);
    
            RunOnUiThread(() =>
            {
                ImageView imgView = FindViewById<ImageView>(Resource.Id.MyImageView);
                imgView.SetImageBitmap(bm);
            });
        }
    }
    

Upvotes: 4

Related Questions