0

現在、一部の作業を UI スレッドから他のスレッドに移動することで、GridView のスクロールをスムーズにしようとしていますが、奇妙な動作が発生します。1 つの画像が複数のビューに描画されることがあります。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() 要求を処理する場合、ビットマップを更新するたびに、そのビットマップ オブジェクトに設定されたリスト内のすべてのセルに新しいビットマップが表示されます。私のアプリケーションでは、一意の ID 値 (リスト インデックス) を ImageView オブジェクトに設定することで、この状況を管理しています。GetView() リクエストが送信されると、ビットマップが再利用され、新しい情報を表示する必要があるかどうかがわかります。また、新しいビットマップを作成する必要があるか、既存のビットマップを再利用する必要があるかを知ることもできます。

ImageView に設定されたビットマップの ID を管理するには、次の 2 つの関数を使用します。

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