我已经开发了一个应用程序,该应用程序以类似于Tinder的UICollectionView显示“全屏卡片”。该卡包含图像和一些文本。我在SDWebImage的单元格中使用sd_setImageWithURLUICollectionView方法加载图像。

但是,这不能给我带来良好的性能,因为大多数图像是在用户使用卡时加载的。因此,我使用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从缓存中获取下载的图像。

这是一个更好的解决方案,因为当用户在卡片上时,我现在正在预加载图像。但是,这是一个并行队列。这意味着图像编号。索引+ 20可以在当前图像之前加载,并且用户可能必须等待该图像。此外,如果用户滚动浏览了50多个卡,并且内存使用量也持续上升,则该应用程序会变得有些滞后。

任何人都可以提出改进建议或更好的算法吗?

谢谢

最佳答案

使用sd_setImageWithURL将图像下载到当前卡上,然后在完成处理程序中开始下载预取队列。这样,当前图像始终享有最高优先级,并且不会滞后。

currentCardImageView.sd_setImageWithURL(url) { (image, error, imageCacheType, url) in
   // start prefetching here
}

如果当前图像已经下载,SDWebImage将识别出该图像并从缓存中获取。

滞后和高内存消耗的另一个问题可以通过减少预取图像的数量来解决。 20相当高,5应该足够,但这取决于图像大小,网络速度等。

另一件事:SDWebImage具有maxConcurrentOperationCount属性。从1开始,测试,增加到2,测试,增加...,依此类推。直到发现问题为止。

10-07 19:54
查看更多