0

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

您可以在下面找到我当前代码的简化版本。LoadShowImageAsync 是从我的 gridview 适配器中的 GetView() 中调用的。如果我调用 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);
            });
        }
    }
}

谢谢!

延斯

4

1 回答 1

0

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

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

ImageView.setTag()
ImageView.getTag()
于 2013-03-19T11:54:12.870 回答