获取图像异步执行错误

时间:2014-06-26 08:16:43

标签: android asynchronous xamarin android-adapter android-bitmap

Xamarin中,我有一个GridView适配器,可为每个GridView项设置图像。此GridView适配器是Fragment加载的ViewPager的一部分。

每个GridView项都有一个显示图像的ImageView。我有一些代码可以在同步下载图像时正确显示图像,但不是异步。

这是我的代码:

public override View GetView (int position, View convertView, ViewGroup parent)
{
    View view = convertView;
    if (view == null)
        view = context.LayoutInflater.Inflate(Resource.Layout.GridViewWithImageAndTextItem, gridView, false);
    imgIcon =  view.FindViewById<ImageView> (Resource.Id.image);
    if (gridViewtems[position].useResourceAsThumbnail) 
    {
        imgIcon.SetImageResource (gridViewtems[position].imageResourceId);
    } else {
        //Code that does work
        imgIcon.SetImageBitmap (GetImageBitmapFromUrl (gridViewtems[position].thumbNailWebAddress));
        //Code that does not work
        DownloadAsyncBitmap (gridViewtems[position].thumbNailWebAddress, imgIcon);
    }
    view.FindViewById<TextView> (Resource.Id.myImageViewText).Text = gridViewtems[position].text;
    return view;
}

async void DownloadAsyncBitmap(string url, ImageView imageView)
{
    var webClient = new WebClient ();
    var uri = new Uri (url);
    byte[] bytes = null;
    try
    {
        bytes = await webClient.DownloadDataTaskAsync(uri);
    }
    catch(TaskCanceledException){
        Console.WriteLine ("Task Canceled!");
        return;
    }
    catch(Exception e){
        Console.WriteLine (e.ToString());
        return;
    }

    Bitmap bitmap = await BitmapFactory.DecodeByteArrayAsync (bytes, 0, bytes.Length);
    imageView.SetImageBitmap (bitmap);
}

private Bitmap GetImageBitmapFromUrl(string url)
{
    Bitmap imageBitmap = null;

    using (var webClient = new WebClient())
    {
        var imageBytes = webClient.DownloadData(url);
        if (imageBytes != null && imageBytes.Length > 0)
        {
            imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
        }
    }

    return imageBitmap;
}

这是尝试使用异步代码时的应用程序输出:

System.MissingMethodException: Constructor on type 'System.Diagnostics.DebuggerBrowsableAttribute' not found.
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   at System.Activator.CreateInstance(Type type, Object[] args)
   at Mono.Debugging.Soft.SoftDebuggerAdaptor.BuildAttribute[T](CustomAttributeDataMirror attr)
   at Mono.Debugging.Soft.SoftDebuggerAdaptor.GetAttribute[T](CustomAttributeDataMirror[] attrs)
   at Mono.Debugging.Soft.SoftDebuggerAdaptor.OnGetTypeDisplayData(EvaluationContext ctx, Object type)

这个确切的代码适用于我的另一个应用程序,但不适用于Google Maps的此应用程序。是否有一些我遗失的许可?

我可以帮助您异步设置图像吗?

提前致谢

修改

感谢您的资源,我已阅读它,现在了解有关异步和等待运算符的更多信息。

这是我目前的代码:

async Task<Bitmap> DownloadBitmapAsync(string url)
{
    var webClient = new HttpClient ();
    var uri = new Uri (url);
    byte[] bytes = null;

    try
    {
        bytes = await webClient.GetByteArrayAsync(uri);
    }
    catch(TaskCanceledException){
        Console.WriteLine ("Task Canceled!");
        return null;
    }
    catch(Exception e){
        Console.WriteLine (e.ToString());
        return null;
    }

    Bitmap bitmap = await BitmapFactory.DecodeByteArrayAsync (bytes, 0, bytes.Length);
    return (bitmap);
}

我正在调用此代码并使用以下代码设置Bitmap

DownloadBitmapAsync(gridViewItems[position].thumbnailImageWebAddress)
    .ContinueWith(continuation => { imgIcon.SetImageBitmap (continuation.Result); });

显示GridView,但ImageView个对象中没有任何图片包含在其中。

我的代码是否正确?

2 个答案:

答案 0 :(得分:0)

ImageView是一个视图,只应在UI线程上进行操作。不确定这是否解决了您的问题:

((Activity)Context).RunOnUiThread (() => {imageView.SetImageBitmap (bitmap);} );

答案 1 :(得分:0)

您正在以错误的方式使用async-await。

首先,你永远不应该从Async任务返回“void”。 因此,您的DownloadAsyncBitmap(专有名称约定是DownloadBitmapAsync)必须返回Task(相当于void),或者更好,Task<Bitmap>

其次,你以错误的方式调用你的任务。有一种名为“async all as way”的方法,它意味着你应该将所有方式返回到顶级接口方法(command,clickEvent或getView)。如果此事件返回void,则异步运行Task非常简单:

public async override void OnStart()
{
    await DoSomethingAsync();
}

你应该明白,async-wait只是围绕任务和延续的语法糖。 因此,如果您的方法无法返回void(如GetView),则可以使用ContinueWith构造。

在您的情况下,从GetView启动异步任务的正确方法是:

DownloadAsyncBitmap(gridViewtems[position].thumbNailWebAddress)
    .ContinueWith(continuation => { imageView.SetImageBitmap (continuation.Result); });

我建议你学习async-await多一点http://msdn.microsoft.com/en-us/library/vstudio/hh191443(v=vs.110).aspx