【问题标题】:Optimally preloading / prefetching images in UICollectionView and UITableView在 UICollectionView 和 UITableView 中优化预加载/预取图像
【发布时间】:2018-01-01 19:09:00
【问题描述】:

我有一个我认为很容易解决的非常常见的情况 - 一个带有 UICollectionView 的应用程序,每个单元格中都有一个图像,该图像是通过 http/https 从 Web 服务器上的 API 获取的。

我正在尝试实现 iOS 10 的 prefetching in UICollectionView,以便提前请求可能需要的图像。

在我看来,最佳预取应该满足各种要求:

  1. 即使图像已经在等待获取的队列中,也应始终优先于推测性预取来获取实际立即需要的图像。
  2. 当 iOS 告诉我们不再需要预取某个特定图像时,应该将它(并且只有它)从预取队列中移除。
  3. 如果请求图像,则应始终传送该图像,除非取消 /all/ 请求(如果在多个单元格或多个视图控制器中使用一个图像很容易出错)。
  4. 如果调用了 didEndDisplaying,则应中止优先提取(但是,如果请求了预取但未取消,则图像应该以较低的优先级留在队列中)。
  5. 仅与图像加载相关的各种常见要求 - 例如。不要用预取请求淹没底层系统,这最终会占用带宽和服务器插槽,远离立即需要的图像。

我查看了各种现有的库,例如 SDWebImageKingfisher,很惊讶这两个库似乎都无法轻松满足上述要求。

例如,SDWebImage 不满足第二个要求 - 您只能 cancel all prefetching,或者您必须为每个图像创建一个预取器(这意味着各种其他 SDWebImage 功能,例如限制 pre 的并发请求数) - 获取的图像 - 即要求 5 - 不再有效。)

这真的是一个难题吗?我错过了一些明显的解决方案吗?我是不是想太多要求了?

【问题讨论】:

    标签: ios uitableview uiimageview uicollectionview prefetch


    【解决方案1】:

    如果从 prefetchItemsAt indexPaths 传递的最新索引路径不够用,您似乎需要实现自己的优先级。

    要求 1、2、3 并使用优先队列(排序堆)来完成。要求 4 取决于您的优先级队列的实现。 5 相当宽泛和模糊,只是限制对您的方法的调用次数以进行获取。 Priority Queue 采用通用类型,因此您可以将它与具有您希望获取的项目的属性的对象/类一起使用,为了简单起见,下面我只使用 IndexPath.row。

    创建一个优先级队列,作为数据源和缓存之间的中介。

    然后通过查看/出列优先级队列并将数据存储在 Kingfisher 中,将数据设置为从您的 DataSource 中获取。 你的数据源 -> PriorityQueue -> Kingfisher -> Cell

    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
         ...
        for indexPath in IndexPaths {
           //Add the indexPath to the top of the priority queue
           //highest priority is determined by the sort function you used when initializing the priority queue. 
           priorityQueue?.enqueue(indexpath.row)
        }
    
       //Call your method for getting the properties
       self.fetchObjectsByPriority() 
    }
    
    
     func fetchObjectsByPriority() {
            if let count = priorityQueue?.count {
            for _ in 0...count {
    
                //get the index
                var index = self.priorityQueue?.dequeue()
                //Alternatively .peek() with out dequeuing item
                //get image data and store
                dataSource[index].image = ...
    
            }
        }
    }
    

    确保使用排序函数初始化优先级队列。

    您可以从here 获得一个预先构建的优先级队列,您还需要一个heap 来创建优先级队列。

    更多关于priority Queuesheap sorting

    如果没有相关代码,就很难提供有效的解决方案。我希望这会有所帮助,欢呼并祝你好运!

    【讨论】:

    • 嗨,预取仅适用于固定大小的collectionviewCell?我尝试使用动态自调整大小并且不调用方法 prefetcheditem
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    相关资源
    最近更新 更多