简而言之,我的项目的解决方案是:thread
下载queue
支持的图像。加上检查目标UI
控制,它没有出列以供重用。
长版:
queue
使用方法Start
/实现Stop
。调用时Start
,启动后台线程,在繁忙循环中(while true { DoSomething(); }
)将尝试从队列中取出请求。如果没有出队,请睡一会儿。如果出队,执行它(下载图像)。Stop
方法应该说线程退出循环:
public void Start()
{
if (started) {
return;
}
started = true;
new Thread (new ThreadStart (() => {
while (started) {
var request = GetRequest();
if (request != null) {
request.State = RequestState.Executing;
Download (request);
} else {
Thread.Sleep (QueueSleepTime);
}
}
})).Start ();
}
public void Stop()
{
started = false;
}
- 然后,使用这样的逻辑创建一个私有方法
queue
来下载图像:检查文件缓存中的图像。如果文件可用,请阅读并返回它。如果没有,请下载它,将其保存到文件中,返回(调用Action<UIImage> onDownload
)或错误(调用Action<Exception> onError
)。queue
在的忙循环中调用此方法。命名它Download
:
public Download(Request request)
{
try {
var image = GetImageFromCache(request.Url);
if (image == null) {
image = DownloadImageFromServer(request.Url); // Could be synchronous
}
request.OnDownload(image);
} catch (Exception e) {
request.OnError(e);
}
}
- 然后,创建一个公共方法将请求添加到队列。模式
Command
对于包装队列请求很有用: storage Actions
, current State
。命名它DownloadImageAsync
:
public DownloadImageAsync(string imageUrl, Action<UIImage> onDownload, Action<Exception> onError)
{
var request = MakeRequestCommand(imageUrl, onDownload, onError);
queue.Enqueue(request);
}
UITableViewCell
准备显示和请求下载图像的时间:
// Custom UITableViewCell method, which is called in `UITableViewSource`'s `GetCell`
public void PrepareToShow()
{
var imageURLClosure = imageURL;
queue.DownloadImageAsync(imageURL, (UIImage image) => {
if (imageURLClosure == imageURL) {
// Cell was not dequeued. URL from request and from cell are equals.
imageView.Image = image;
} else {
// Do nothing. Cell was dequeued, imageURL was changed.
}
}, (Exception e) => {
// Set default image. Log.
});
}
检查 (imageURLClosure == imageURL) 对于避免在UIImageView
快速滚动时将多个图像合二为一很重要。一个单元格可以初始化多个请求,但只能使用最后一个结果。
进一步的改进:
- LIFO 执行。如果尚未运行任何请求,请添加新请求以开始。
- 使用
Action<byte[]> onDownload
而不是Action<UIImage> onDownload
实现跨平台代码兼容性;
download image
当单元格变得不可见时取消请求的可用性( WillMoveToSuperview
)。好吧,这不是很有必要。首次下载后,图像将在缓存中,因此任何进一步的图像请求都将快速完成。感谢缓存;
- 内存缓存。因此,在最坏的情况下,链将是:
Find image in in-memory cache
-> Find image in file cache
-> Downloading from server
。