图像被分配到的ListView的另一行项目 [英] Image is assigned to another row item of ListView

查看:146
本文介绍了图像被分配到的ListView的另一行项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道等待异步设置它的适配器之前,是非常方便的为一个ListView / GridView的prepare数据。例如:

I know async await is very handy to prepare data for a ListView/GridView before its adapter is set. For example:

// in Activity.cs
async void OnCreate(Bundle SavedInstanceState)
{
    SetContentView(...);
    ListView listView = FindViewById<ListView>(...);
    AdapterData data = await Task.Run(() => GetDataFromWorkerThread);
    listView.SetAdapter(data);
}

不过,我需要的是:

But what I need is :

// 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);
}

所以有时 convertView GetView()返回ResizeImageAsync()结束。问题是 image01 这是应该在第一行的的ImageView被分配现在,而不是被分配到第二或第三行的的ImageView 。任何人都知道如何解决这个问题?

So sometimes convertView in GetView() is returned before ResizeImageAsync() is finished. The problem is image01 which was supposed to be assigned in first row's ImageView is now instead being assigned to the second or third row's ImageView. Anyone knows how to solve this issue?

推荐答案

问题不是返回的看法,但它熄灭屏幕,并重复使用。然后,你火了另一种异步方法和最后成品的胜利。这就是说,你不得不取消你的第一个启动另一对同样的观点。一种解决方案是使用CancellationTokenSource您在View.Tag存储。这就给了你一个方法来取消previously没有完成异步方法。

The problem is not that view is returned but that it goes out of screen and is reused. Then you fire up another async method and last finished wins. That said you have to cancel the first one of you start another on same view. One solution is to use CancellationTokenSource which you store in View.Tag. That gives you a way to cancel previously not finished async method.

下面是一个不真正的测试换语法错误code.Note的存储.NET对象为View.Tag需要的包装。另外请注意,这code可能不是完美的,但它应该说明做什么。

Here is a not-really-tested-for-syntax-errors code.Note that storing a .net object into View.Tag requires a wrapper. Also note that this code might not be perfect but it should illustrate what to do.

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;
    }

这篇关于图像被分配到的ListView的另一行项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆