GetView,视图,位图和多线程的问题

时间:2013-03-19 11:39:00

标签: android xamarin.android

我目前正试图通过将一些工作从UI线程移动到其他线程来使我的GridView滚动更顺畅,但我得到了奇怪的行为:有时一个图像被绘制到多个视图。我正在使用Xamarin(C#)。

您可以在下面找到我当前代码的简化版本。从我的gridview适配器中的GetView()内调用LoadShowImageAsync。如果我调用LoadShowImageDoWork()单线程,一切都很好但是当我通过ThreadPool调用它时,它显示了奇怪的行为。 在调试日志中,我看到该方法在解码图像后留下,并且RunOnUiThread的东西在以后的几个图像中被组合执行。然后一些其他图像被解码,然后RunOnUiThread组合完成它们。我想不知怎的,位图内容在这里混淆了。

有谁知道我能做些什么才能让它工作多线程?

public class LoadImageAsyncDatas {
    public int ImageId { get; private set;}
    public ImageView ImageView { get; private set;}

    public LoadImageAsyncDatas (ImageView imageView,int imageId) {
        ImageId = imageId;
        ImageView = imageView;
    }
}

public class LoadImageAsync {

    private object locker;
    Activity activity;

    public LoadImageAsync (Activity activity) {
        this.activity = activity;
        locker = new object ();
    }

    public void LoadShowImageAsync (ImageView imageView,int imageId) {
        object stateInfo = new LoadImageAsyncDatas (imageView, imageId);
        // call LoadShowImageDoWork() either multithreaded (strange behaviour) or single threaded (works)
        ThreadPool.QueueUserWorkItem (new WaitCallback (LoadShowImageDoWork), stateInfo);
        // LoadShowImageDoWork (stateInfo);
    }

    private void LoadShowImageDoWork (object stateInfo) {
        lock (locker) {     // lock is only for debugging
            LoadImageAsyncDatas imageData = stateInfo as LoadImageAsyncDatas;

            byte[] imageBytes = LoadFileByImageId(imageData.ImageId);
            Bitmap bitmap = BitmapFactory.DecodeByteArray (imageBytes, 0, imageBytes.Length, myBitmapOptions);

            activity.RunOnUiThread(() => {
                imageData.ImageView.SetImageBitmap(bitmap);
            });
        }
    }
}

谢谢!

1 个答案:

答案 0 :(得分:0)

如果您希望Android列表控件中的每个位图都是唯一的,那么您必须为显示屏上的每个可见“单元格”管理唯一的位图。如果您尝试重新使用当前用于显示另一个单元格的位图,您将更改它们。例如,如果使用单个位图来处理列表的所有GetView()请求,则每次更新位图时,列表中设置为该位图对象的所有单元格都将显示新的位图。在我的应用程序中,我通过在ImageView对象中设置唯一ID值(列表索引)来管理这种情况。当发送GetView()请求时,我可以判断位图是否已被重用,现在需要显示新信息。它还允许我知道何时需要创建新位图而不是重用现有位图。

使用这两个函数来管理在ImageViews中设置的位图的ID:

ImageView.setTag()
ImageView.getTag()