UIScrollView懒惰加载策略扭曲

时间:2010-11-21 20:53:55

标签: iphone uiscrollview lazy-loading

我有一个水平滚动的UIScrollview,启用了分页。每个页面代表一个数据Feed。每个数据馈送消耗相当大的内存,包括UITableView中显示的文本和图像。由于用户可以拥有无​​限量的数据馈送,因此我需要延迟加载它们以防止最大限度地减少内存使用量。我的想法是在任何给定点保持内存中最多5个数据源,并释放超出该范围的任何内容。我最初的看法是将页面保留在内存中的视口中,并将页面保留在其中的任意一侧。这样,当用户滚动时,下一个连续页面将始终在内存中并将快速显示。

这是我的问题: 我们还需要支持一种情况,用户可以跳到特定的数据源,可能是向右或向左的10个或更多页面,这会将我的整个延迟加载方案抛出窗口。

可能有更好的策略来支持这种情况吗?

3 个答案:

答案 0 :(得分:7)

是的,您可以做的是创建一个外部滚动视图,其中包含类似于tableview的单个单元格。在这方面,单元格有一个内容视图,你可以放置你的数据,让我们假设你知道如何做到这一点。

一旦你掌握了这个架构,就会变得相当清楚:你可以知道你的单元格的宽度和屏幕的大小,一些简单的数学可以告诉你屏幕上有多少,你可以向左或向右添加一个,这样就可以在用户滚动时预加载一些数据。

这将说明,让您能够在内存中,最多5个Feed,如果3个可见,在滚动视图的内容视图的开头或结尾,4个Feed,无论您是否有十亿饲料。

其中一个关键部分是细胞再利用。你保留了几个NSSet个,一个用于回收细胞,一个用于可见细胞。将已离开屏幕的项目添加到回收的单元格中,在设置单元格时从回收的单元格中将项目出列,以节省额外的内存分配,这可能很昂贵。请记住,使用此策略,对于细胞重用,您仍然对UITableView的注意事项持主观态度。

我正在插入我在这里写的一些软件,所以请原谅我,但我这样做是作为我正在谈论的一个例子,如果你实施我在这里讨论过的问题,它是可用的{{3 }}

最后一点说明。为了支持跳过单元格,只需简单的数学计算就可以调整滚动视图中的点。对此的操作可以通过手势完成,但现在我们正在谈论一个平移手势识别器,具有一些特定于您的应用程序的特定属性,作为示例。或者你可以使用按钮,如果你真的必须。只需确保您知道如何计算单元格的偏移量,然后滚动到该点。你没事。

答案 1 :(得分:1)

很难就问题中提供的信息提供准确的建议。因此,我将在阅读问题时提出一些想法。

下载Feed需要很长时间吗?是否可以只下载一些项目(一个屏幕)来立即显示前几个项目?如果可能,也许懒惰加载图像。

您是否考虑过在磁盘上缓存Feed数据?这样,您可以立即显示一些数据,然后在下载新数据时更新Feed。

由于每个页面都是一个Feed视图,用户是否只是滚动浏览Feed而不查看它?你真的需要在每一侧加载2个视图,或者你可以在每一侧只看到1个视图。

我认为您的延迟加载方案不会因为用户可以直接跳到任何页面而停止工作。您必须在选择该页面时开始加载该页面的数据,但是通过使用磁盘缓存或下载小样本可以使应用感觉更快。我还认为使用某种动画来动画选定的页面可能会给你带来一点时间。

答案 2 :(得分:1)

  

这是我的问题:我们还需要支持这样一种场景:用户可以跳到特定的数据源,可能是向右或向左的10个或更多页面,这会将我的整个延迟加载方案抛出窗口。

然后你需要修复你的数据结构。我写的几乎就是这个(类似于UITableView的分页滚动视图)并且它工作正常(有一些重载怪癖,但是嘿......)。

  • 跟踪您加载的页面。我使用了类似于ring-buffer的模8,花了一段时间才得到正确的代码;使用带有NSNumber键和UIView值的NSDictionary可能要容易得多。这意味着当您从第1页更改为10时,您仍然可以告知加载的视图适用于第1,2和3页,并将其删除。
  • 在-layoutSubviews中加载所需的页面。我会加载1或3; 5可能太多了(但如果你在页面之间,你需要加载至少2个。)
  • -scrollViewDidScroll:中加载3(一侧到一侧)。这样,当您从第1页滚动到第2页时,它不会尝试加载第4页(尚未加载)。
  • 如果willDecelerate为NO,–scrollViewDidEndDragging:willDecelerate:–scrollViewDidEndDecelerating:–scrollViewDidScrollToTop:,请在–scrollViewDidEndScrollingAnimation:中加载5(两侧到两侧)。这个想法是动画结束了,所以你可以在没有用户感知滞后的情况下加载额外的视图。
  • 可能会在–scrollViewWillBeginDragging:中加载5,以确保在目前第1页上加载了第3页。

我决定“双面打两页”,因为当你从第1页轻弹到第2页时,它经常会在第3页反弹时显示像素范围的条子。使用滚动视图插入可以避免这种情况,但我们当时没有想到(oops)。除此之外没有太多理由选择5比3。

要做到这一点有点工作,但在其他方面似乎完美无瑕。