GMGridView セルの画像を読み込もうとしています。問題は、画像の読み込みプロセスがそれほど速くないことです。そのため、マルチスレッド化することにしました。背景画像をロードするための優れたオールインワン クラスを作成しました。その内容は次のとおりです。
public void LoadImageIntoView (string imageURL, UIImageView imageView, int index)
{
rwl.AcquireReaderLock (Timeout.Infinite);
if (disposed)
return;
UIImage image;
lock (locker) {
cache.TryGetValue (imageURL, out image);
}
if (image != null)
imageView.Image = image;
else {
new Thread (() => {
if (MediaLoader.IsFileCached (imageURL))
LoadImage (index, imageURL);
else {
MediaLoader loader = new MediaLoader ();
loader.OnCompleteDownload += (object sender, OnCompleteDownloadEventArgs e) => {
if (e.Success)
LoadImage (index, e.FileURL);
};
loader.GetFileAsync (imageURL, false, DownloadPriority.Low);
}
}).Start ();
}
rwl.ReleaseReaderLock ();
}
private void LoadImage (int index, string imageURL)
{
rwl.AcquireReaderLock (Timeout.Infinite);
if (disposed)
return;
string pathToFile = MediaLoader.GetCachedFilePath (imageURL);
UIImage uiImage = UIImage.FromFile (pathToFile);;
// Load the image
if (uiImage != null) {
lock (locker) {
cache [imageURL] = uiImage;
}
BeginInvokeOnMainThread (() => InsertImage (false, index, uiImage));
}
rwl.ReleaseReaderLock ();
}
private void InsertImage (bool secondTime, int index, UIImage image)
{
rwl.AcquireReaderLock (Timeout.Infinite);
if (disposed)
return;
UIImageView imageView = FireGetImageViewCallback (index);
if (imageView != null) {
CATransition transition = CATransition.CreateAnimation ();
transition.Duration = 0.3f;
transition.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
transition.Type = CATransition.TransitionFade;
imageView.Layer.AddAnimation (transition, null);
imageView.Image = image;
} else {
if (!secondTime) {
new Thread (() => {
Thread.Sleep (150);
BeginInvokeOnMainThread (() => InsertImage (true, index, image));
}).Start ();
}
}
rwl.ReleaseReaderLock ();
}
LoadImage メソッド内で画像をロードするために、次のコードも試しました。
UIImage loadedImage = UIImage.FromFile (pathToFile);
CGImage image = loadedImage.CGImage;
if (image != null) {
CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB ();
// Create a bitmap context from the image's specifications
CGBitmapContext bitmapContext = new CGBitmapContext (null, image.Width, image.Height, image.BitsPerComponent, image.Width * 4, colorSpace, CGImageAlphaInfo.PremultipliedFirst);
bitmapContext.ClearRect (new System.Drawing.RectangleF (0, 0, image.Width, image.Height));
// Draw the image into the bitmap context and retrieve the
// decompressed image
bitmapContext.DrawImage (new System.Drawing.RectangleF (0, 0, image.Width, image.Height), image);
CGImage decompressedImage = bitmapContext.ToImage ();
// Create a UIImage
uiImage = new UIImage (decompressedImage);
// Release everything
colorSpace.Dispose ();
decompressedImage.Dispose ();
bitmapContext.Dispose ();
image.Dispose ();
}
アプリをビルドして試してみると、ImageLoader によって返された画像の中にアーティファクトが含まれているように見えることがあります。ランダムな場所にある白い長方形である場合もあれば、予期しない色のピクセルである場合もあります。アプリが AppStore に公開されようとしており、この問題は大きな頭痛の種であるため、この問題の解決策を聞いてとてもうれしく思います。
PS FireGetImageViewCallback は、クラスのコンストラクターで設定したデリゲートを介して UIImageView を返します。Cache は Dictionary 、locker は単なるオブジェクト、rwl は ReaderWriterLock インスタンスです。