我开发了一个应用程序,显示"全屏卡"在UICollectionView
喜欢Tinder。该卡包含图像和一些文本。我在SDWebImage
的单元格中使用sd_setImageWithURL
UICollectionView
方法加载图片。
然而,这并没有给我带来良好的表现,因为当用户在卡上时,图像大多是加载的。因此,我使用SDWebImagePrefetcher
预取队列执行此操作,如下所示: -
func startImagePreloadingOperationForIndex(index:Int)
{
let numberOfImagesToBePreloadedOnEachSide = 20
var previousIndex = index - numberOfImagesToBePreloadedOnEachSide
var nextIndex = index + numberOfImagesToBePreloadedOnEachSide
if previousIndex < 0
{
previousIndex = 0
}
if nextIndex >= currentNewsCollection.count
{
nextIndex = currentNewsCollection.count - 1
}
if previousIndex >= nextIndex || currentNewsCollection.isEmpty
{
return
}
let arrayOfNewsStories = currentNewsCollection[previousIndex...nextIndex]
let arrayOfImageURLs = arrayOfNewsStories.map( { ImageUtility.getImageStringForNewsStory($0) } )
SDWebImagePrefetcher.sharedImagePrefetcher().prefetchURLs(arrayOfImageURLs, progress: { (x, y) -> Void in
}) { (x, y) -> Void in
}
}
当用户登陆特定卡时,将调用此功能。预取队列自动管理不下载缓存中的图像,因此我不必担心这一点。除此之外,我还使用sd_setImageWithURL
中的cellForItemAtIndexPath
从缓存中获取下载的图像。
这是一个更好的解决方案,因为我现在正在用户在卡上时预加载图像。但是这是一个并行队列。这意味着图像没有。可以在当前图像之前加载index + 20,并且用户可能必须等待图像。如果用户滚动超过50张卡并且内存使用率也继续上升,那么应用程序也会变得有点迟钝。
有人可以建议改进这个或更好的算法吗?
由于
答案 0 :(得分:6)
使用sd_setImageWithURL在当前卡上下载图像,并在完成处理程序中开始下载预取队列。通过这种方式,当前图像始终具有最高优先级并且不会滞后。
currentCardImageView.sd_setImageWithURL(url) { (image, error, imageCacheType, url) in
// start prefetching here
}
如果已下载当前图像,SDWebImage将识别此内容并从缓存中获取它。
可以通过减少预取图像的数量来解决滞后和高内存消耗的另一个问题。 20是相当高的,5应该足够了,但这取决于图像大小,网络速度等...
另一件事:SDWebImage有一个maxConcurrentOperationCount属性。从1开始,测试,增加到2,测试,增加......等等。直到你发现它落后的点。
答案 1 :(得分:1)
我建议处理你自己的队列,将图像保存到磁盘,然后从磁盘加载它们。
使用串行队列,或者至少调低并行连接数
,而不是并行队列答案 2 :(得分:1)
我在我正在开发的App上解决了一个类似的问题。在我的应用程序上有成千上万的用户,每个用户可能都有一个头像。
为了提高性能,我开发了一个3级控制器来管理头像请求。
首先,我检查NSCache(我保存到NSCache的所有最近使用的头像 - 由iOS处理,所以我不必在任何需要时关心释放缓存)。您只需要定义几个参数来配置NSCache。
如果在NSCache上找不到头像,我会检查我的本地Db(Sqlite),其中最近使用的头像保存为Blob字段。请记住,有时您需要在本地Db上执行清理,释放旧数据以保存设备内存。
如果仍未找到,我使用LIFO方法将请求保存在队列中(后进先出)。这意味着每当本地用户滚动用户列表时,屏幕上当前用户的头像应该在已经超出表格视图屏幕之前获得。
再次,再次增加性能(根据您的选择决定),当用户快速滚动屏幕时,我不要求任何下载。每当用户放慢表视图滚动时,我就开始请求下载。除此之外,我限制了paralel下载的数量。只要下载插槽打开(成功或失败),就会启动新的下载。
这些优化对我来说非常有效,我的应用程序运行良好。
我希望它可以帮助你。