负载平衡
在 UITableView 中,当一个元素出现在屏幕上时,你必须
同步渲染它。这意味着你有不到 16 毫秒的时间
做。如果你不这样做,那么你会丢弃一帧或多帧。如果你是
渲染新闻提要故事等复杂元素,基本上是
不可能满足这个时间表,所以你注定要丢帧。
使用 ListView,当您到达当前屏幕的末尾时,您可以
提前准备更多要渲染的行。这些行将是
在不同的线程中呈现,因此不会冻结 UI 线程
加工。它工作的原因是负载不
均匀分布。你不需要在每一个单曲上呈现一个新故事
框架,大多数框架只是滚动,不需要新故事
出现。
ListView 也会一次渲染一个元素,所以如果你是
在渲染更多行时与某些元素交互,它不会
阻塞,直到所有行都被预渲染,它只会阻塞
一行。
内存管理
UITableView 在内存方面非常保守,它积极地重用
细胞。这个决定是在 iPhone 1 中做出的
极其稀缺。问题在于重用单元格是
开发人员极易出错。给你一个脏东西,
你不知道发生了什么突变,你需要
重新配置它看起来像你想要的。在我们的 iOS 应用程序中,这导致
错误太多了。
重用cell的问题是有些cell有内部状态
(视频播放器运行、文本输入、水平滚动位置...)当
您重用它们,您需要能够序列化该状态并将其放入
背部。这并不总是可能的,也不容易,所以你通常要么
松开此状态,否则它会在新行上传播并导致错误。
我们在 React Native 上发现它在 iPhone 上足够快
4s 为每一行创建新的单元格。所以,我们不需要
把这个非常严格的约束强加给我们自己。在您的屏幕截图中,您
注意到您滚动一段时间后我们不会删除行。
这不完全正确,我们不删除虚拟 dom
React 方面的表示(你在 chrome 开发中看到的)
工具),但我们确实从“dom”中删除了这些元素并保留它们
参考。
当它们再次可见时,我们将它们放回 dom。万一我们
内存不足或列表太大,我们可能会销毁这些和
从头开始重新创建它们(失去上面提到的状态)
未来。我们还没有做这个性能优化,但是
用户代码不会受到影响。
我们试图积极地删除 iOS 视图,但我们发现
这样做实际上非常昂贵。最好离开他们
挂起而不是删除它们。
变化检测
在 ListView 中,我们有一个支持不变性的 DataSource 对象。如果
你有一个包含 1000 个元素的列表来渲染,你想让那些
1000 个元素不可变,这意味着您可以检查前一个
=== 下一个并立即知道是否发生了变化。这样,当任何事情发生变化时,您唯一要做的就是遍历
这两个列表并进行那些非常快速的平等检查并知道什么
行改变了。然后只更新那些。
布局
在 UITableView 中,你必须指定每一行的布局
即使它们没有显示在屏幕上。所以,在某些情况下
它不是固定大小,您必须基本上将元素渲染为
知道它的大小,并预先支付高昂的成本。这也很
手动操作很烦人。
在 ListView 中,由于 React Native 拥有布局系统,你不需要
自己做所有艰苦的手动计算。当一行是
渲染,它会更新大小。唯一的缺点是
滚动条有点时髦,但我相信我们能上来
用启发式方法在未来平滑它。