我試圖加載GMGridView單元格的圖像。問題是,圖像加載過程並不那麼快,所以我決定去多線程。我爲背景圖片加載創建了一個很好的一體化類。下面是它的內容:在後臺加載UIImage中的文物
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,這個問題是一個非常頭疼的問題。
P.S. FireGetImageViewCallback通過我在類的構造函數中設置的委託返回一個UIImageView。 Cache是一個Dictionary,locker只是一個對象,rwl是一個ReaderWriterLock實例。
工件是否只出現在多線程中?多線程實際上是否可以提高性能?圖像從哪裏加載? –
圖像是從文件系統加載的,是的,它們中的很多需要花費一些時間才能在UI線程上加載。平滑滾動是不可能的,所以多線程是我唯一的選擇。我會再次用Ui線程加載圖像來測試我的應用程序,但是我記得當時沒有問題。 – Danchoys
UIKit不是線程安全的。您必須僅從主線程更新UI。將UI的所有更新強制到主(UI)線程。您可以在後臺線程加載到NSData,然後從主線程上的NSData更新映像。我很好奇這是否能夠提高性能。 –