我正在尝试为 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 实例。