1 sduoduo233 2024-07-22 23:33:46 +08:00 via Android 安卓是 recyclerview |
![]() | 2 abcbuzhiming 2024-07-22 23:39:09 +08:00 移动端我不清楚。但是桌面端的话,我没听说过传统 UI 的列表控件有用虚拟滚动的,实际上,当元素量够大的时候,一样会卡的,只是桌面端大部分时候处于性能溢出的状态,且内存管够,所以一般遇不到那个能让你卡的数量级。 |
3 Irisxx 2024-07-22 23:40:59 +08:00 via iPhone 主要是归功于对象池的重用机制,辅之以 LRU 这些缓存机制优化。 |
![]() | 4 verrickt 2024-07-22 23:52:49 +08:00 via Android 微软的 GUI 框架把相关的技术叫做 UI Virtualization ,有兴趣可以看看 |
![]() | 5 lmw2616 2024-07-22 23:56:57 +08:00 android 用 recyclerview ,也是类似于虚拟滚动 |
![]() | 6 usVexMownCzar 2024-07-22 23:58:52 +08:00 你搜索 iOS UITableView 应该能搜到 很早之前的经典面试题,说一下 UITableView Cell 的复用原理 |
![]() | 7 kemchenj 2024-07-22 23:59:56 +08:00 其它端不清楚,iOS 端其实就是虚拟滚动,列表会维护一个重用池,把不可见的 cell 塞进去,然后需要展示的时候从里面拿 cell 出来显示,如果发现不够就再补充新的进来 iOS 封装得还行,但也免不了各种限制和小毛病,都是需要开发者额外做一些处理去完善体验,例如预先计算每个元素的高度以便把列表撑开之类的... 感兴趣的话可以搜一下“UITableView 重用” |
8 A4l1CteRQHlG1Bs8 2024-07-23 00:45:14 +08:00 via Android 回收,重用,缓存 |
![]() | 9 UnluckyNinja 2024-07-23 01:10:27 +08:00 如果从只渲染可见部分的组件来看,那基本上都可以算作虚拟滚动(否则就是加硬件了) 你用的库总是有各种各样的不完美,可能是因为复杂度难以实现/怕导致库臃肿(所以固定高度),或者虚拟高度计算不正确。 根本原因在于虚拟高度需要根据内部组件的实际大小调整以正确计算滚动位置。 你看像 twitter 也是虚拟滚动,但你要是快速拉到中间再缓慢向上拉,会发现 twitter 的滚动条也在闪,(猜测)这就是在修正假定的未渲染元素的高度到渲染完后实际高度,并相应调整总高度。 如果你是想写前端的一个虚拟滚动组件,可以参考 VueUse 推荐的这个独立虚拟滚动组件 https://vue-virtual-scroller-demo.netlify.app/dynamic |
![]() | 10 superkeke 2024-07-23 09:14:07 +08:00 iOS UITableView ,android recyclerview ,移动端这是最基本的了。 |
11 tangmanger 2024-07-23 09:17:21 +08:00 wpf 大列表有虚拟化 只渲染展示的 |
12 shunia 2024-07-23 09:25:42 +08:00 解决方案全都是虚拟列表,没有例外。方案细节基本就是元素复用、列表两端留缓冲区、高度重新计算等。 你觉得不好用是因为这个没有完美的解决方案,比如你说的等高问题,应该是想要考虑保留列表滚动位置,否则根本不必等高。 这些都是一说出来就明白的基础原理,并不是哪个技术方案本身能解决的,桌面端列表大了不虚拟也会卡的爆炸,只是在同一个硬件设施上比网页端能多承受一些而已。 |
13 hefengwqz 2024-07-23 09:27:12 +08:00 @abcbuzhiming 桌面端我们之前开发性能调优工具的时候,数据表格就是做的虚拟滚动,Android 手机录制几十秒解析出来的数据就有百万条。 |
![]() | 14 duanxianze 2024-07-23 09:43:11 +08:00 都是虚拟滚动,上千上万的元素啥玩意也顶不住的,只不过浏览器的限制导致 dom 复用总有问题,安卓 ios 和 win 内置的相关逻辑 |
15 chniccs 2024-07-23 09:54:42 +08:00 安卓最开始的时候是 listview ,后面换成了 recyclerview ,不过都是复用,但是当年试过,不复用的话,列表内容不复杂,不是太快的滑动也没有很卡,只是内存会爆 |
16 wya93 2024-07-23 09:55:41 +08:00 虚拟分页, |
17 iOCZS 2024-07-23 10:08:05 +08:00 反正你只能看到一个屏幕的东西,我提前准备好三屏,够你看的了 |
18 zpxshl 2024-07-23 10:14:56 +08:00 via Android 你搜不到是因为,安卓列表基本都用 rv 实现,不存在问题,自然没有“解决方案” |
![]() | 19 unco020511 2024-07-23 10:15:02 +08:00 ![]() 移动端的列表控件会在背后做非常多的工作,以便解决列表渲染的性能.就拿 android 端的 recyclerview 举例: 1. 视图复用( View Recycling ):RecyclerView 通过 ViewHolder 模式来复用已经创建的视图。简单来说,当某个视图滚出屏幕时,它不会被销毁,而是会被放入一个"回收池"中。当新的视图需要显示时,RecyclerView 会从这个回收池中取出一个视图,并绑定新的数据。这大大减少了视图创建和销毁的开销。 2 .按需加载( Lazy Loading ):RecyclerView 只会创建和绑定当前屏幕上可见的视图,以及少量即将进入屏幕的视图。这样可以有效减少内存消耗和处理时间。 3. 布局管理器( LayoutManager ):RecyclerView 使用 LayoutManager 来决定如何在屏幕上排列子视图。不同的 LayoutManager 可以实现不同的布局方式,如线性布局、网格布局等。LayoutManager 负责计算哪些视图需要显示,哪些可以复用。 4 .差分更新( Diff Util ):RecyclerView 支持高效的数据更新。当数据集发生变化时,可以使用 DiffUtil 来计算新旧数据集之间的差异,只更新那些真正改变的部分,而不是重新渲染整个列表。 |
![]() | 20 debuggerx 2024-07-23 10:16:35 +08:00 条目非等高的长列表还要带滚动条,原理上就没办法高效、完美解决,只能是各种取舍,有时是技术上,有时是设计上。 或者换句话说,只要原理上无法避免大量元素 layout 的场景,怎么都会卡,只是在同等硬件配置下不同的语言和框架会出现卡顿现象的量级会有所不同。 |
![]() | 21 codehz 2024-07-23 10:21:34 +08:00 (其实浏览器也不会绘制超过屏幕的内容( edge 有几个版本你就会在滚动过快的时候看到白屏被一个个方块填上的过程),但超过屏幕的内容不止是绘制的问题,还有布局等其他因素需要计算,加上为了 js 访问方便而设计的对象接口的 overhead 才会显得不能装太多东西,实际上就单纯说显示一个巨大的表格来说浏览器问题不是很大,好多设计起来就只有单页的文档(例如隔壁的 rust 的某文档,html5 的单页 spec ),其内容长度远超一般“无限滚动”正常用户能滚动到的范围,也可以顺利的在浏览器上呈现。。。(当然和一般无限滚动场景不同的是,它内容上是较为简单的,计算布局的压力也会小很多) 桌面端除了用虚拟滚动的思路之外,还有一种叫 imgui 的思路,其抛弃了控件的抽象,根据滚动位置直接计算出需要展示的范围,然后每次都只画用到的部分,也可以解决这个问题==(有一些商业表格控件就是这个思路) 之所以虚拟滚动一类的机制需要使用“复用”,其本质不是绘制元素有多慢,而是为了表达这个 UI 对象抽象带来的额外成本很高,不能简单的丢弃再重建,或者干脆建立一大堆放着 |
22 ZGame 2024-07-23 13:56:14 +08:00 上面的都说了虚拟滚动,其实网页端还有种做法就是自己用画布做渲染。 |
![]() | 23 shadowyue 2024-07-23 14:02:11 +08:00 关于你说的,移动端有多少 DOM 就渲染多少 DOM ,这个是测试出来的结果吗? 这个问题应该是和样式有关,移动端的元素通过样式来定位有不少方式。 导致很多情况,不全部渲染出来就无法确定一个 dom 的真实位置。 但是据我所知浏览器也是尝试做了优化的,比如你包含很多 video 或者 canvas 元素的话, 一般情况下,不在可视范围是不会去渲染的。 |
![]() | 24 lshbosheth 2024-07-23 14:02:32 +08:00 |
![]() | 25 b821025551b 2024-07-23 14:04:28 +08:00 不卡么?去 12306 上搜一下惠州到东莞的车票试试 |
![]() | 26 rb6221 2024-07-23 14:32:17 +08:00 你可以理解为虚拟滚动,但是他和 web 端的区别是:第一,他是官方维护的,第二,他的语言和框架就决定了性能够好。 |
29 icloudguizhou 2024-07-23 14:48:20 +08:00 @b821025551b 最流畅的还是 M3Max 芯片 128GB RAM 的 mac 上安装拼多多 APP 买高铁票,一键免密支付还可以调用 touchID ,fantastic and smooth experiences than ever before, ![]() |
30 icloudguizhou 2024-07-23 14:52:13 +08:00 |
![]() | 31 LavaC 2024-07-23 15:05:32 +08:00 不定高的元素本来就没法实现完全准确的虚拟滚动,不渲染不知道高度->不知道高度就没法给你正确的 padding |
33 qrobot 2024-07-23 15:09:18 +08:00 @LavaC 我自己实现的虚拟滚动, 在快速滚动下不闪动, 并且性能很强, 我试过 10w 列 * 10w 行, 这个时候才开始卡顿, 而且这个时候的卡顿还有优化空间 |
34 Anarchy 2024-07-23 15:21:03 +08:00 via Android 感觉搜不到 Android 虚拟滚动是这部分属于默认实现了,导致根本不理解什么是虚拟滚动。我刚开始学其他平台都好奇怎么没有 ListView 的组件只有个 scroll view ,都不怕卡的么。 |
35 rcocco OP 学到了,原来各端其实都得做虚拟化列表,有的是开发者自己做,有的是原生控件内部在做。 感谢大佬们 |
36 furlxy 2024-07-23 19:09:48 +08:00 iOS UITableView 享元模式 |
37 jones2000 2024-07-23 22:38:13 +08:00 虚拟表格+画布自己绘制表格,10W-100w 条数据显示完全不卡。 |
![]() | 38 Chuckle 2024-07-24 11:10:08 +08:00 ![]() @LavaC 写过个不定高的虚拟瀑布流 demo ,准确的布局还是做得到的,https://list.qcqx.cn/#/list/virtualwaterfall |
39 HangoX 2024-07-24 17:36:20 +08:00 只有 web 端才有虚拟滚动的概念,其他平台都是原生滚动。虚拟滚动是相对于浏览器的滚动条而说。原生开发本来就是那个滚动条。只是原生开发都考虑会回收利用问题 |