mac*_*Jun 2 c# android xamarin.android async-await xamarin
我知道async await非常方便在设置适配器之前为ListView/GridView准备数据.例如:
// in Activity.cs
async void OnCreate(Bundle SavedInstanceState)
{
SetContentView(...);
ListView listView = FindViewById<ListView>(...);
AdapterData data = await Task.Run(() => GetDataFromWorkerThread);
listView.SetAdapter(data);
}
Run Code Online (Sandbox Code Playgroud)
但我需要的是:
// in ListViewAdapter.cs
public override View GetView (int position, View convertView, ViewGroup parent)
{
if(convertView == null)
{
// create new view
}
ImageView imgView = convertView.FindViewById<ImageView>(Resouce.Id.img_view_id);
ResizeImageAsync(imgView, imgResId);
return convertView; // convertView is returned before ImageView is assigned with resized image
}
private async void ResizeImageAsync(ImageView imageView, int imgResId)
{
Bitmap bmp = await Task<Bitmap>.Run(() => ResizeImage(imgResId, 50, 50));
imageView.SetImageBitmap(bmp);
}
Run Code Online (Sandbox Code Playgroud)
所以有时convertView在完成GetView()之前返回ResizeImageAsync().image01应该在第一行中分配的问题ImageView现在改为分配给第二行或第三行ImageView.谁知道如何解决这个问题?
问题不在于返回视图,而是它退出屏幕并被重用.然后你启动另一个异步方法并最后完成胜利.那说你必须取消第一个在同一个视图上启动另一个.一种解决方案是使用您存储在View.Tag中的CancellationTokenSource.这为您提供了一种取消以前未完成的异步方法的方法.
这是一个没有经过严格测试的语法错误代码.请注意,将.net对象存储到View.Tag中需要一个包装器.另请注意,此代码可能不完美,但应说明要执行的操作.
public override View GetView(int position, View convertView, ViewGroup parent)
{
CancellationTokenSource cts;
if (convertView == null)
{
// create new view
}
else
{
if (convertView.Tag != null)
{
var wraper = convertView.Tag.JavaCast<Wrapper<CancellationTokenSource>>();
if (wraper != null)
wraper.Data.Cancel();
}
}
ImageView imgView = convertView.FindViewById<ImageView>(Resource.Id.img_view_id);
cts = new CancellationTokenSource();
ResizeImageAsync(imgView, imgResId, cts.Token);
convertView.Tag = new Wrapper<CancellationTokenSource> { Data = cts };
return convertView; // convertView is returned before ImageView is assigned with resized image
}
private async Task ResizeImageAsync(ImageView imageView, int imgResId, CancellationToken ct)
{
Bitmap bmp = await Task<Bitmap>.Run(() => ResizeImage(imgResId, 50, 50), ct);
if (!ct.IsCancellationRequested)
{
imageView.SetImageBitmap(bmp);
}
}
public class Wrapper<T>: Java.Lang.Object
{
public T Data;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1438 次 |
| 最近记录: |