Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
FtnApp 的缩略图实践
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Frank Xu
August 26, 2012
Programming
77
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
FtnApp 的缩略图实践
Frank Xu
August 26, 2012
More Decks by Frank Xu
See All by Frank Xu
Proxy Pattern
yyfrankyy
0
110
微信读书阅读器架构
yyfrankyy
2
2.3k
Watcher - EventBus Reinvented
yyfrankyy
0
170
SQLite 调优实践
yyfrankyy
0
160
JSDoc 的使用
yyfrankyy
0
170
交易平台化(前端)
yyfrankyy
0
200
淘宝搜索前端优化
yyfrankyy
0
220
淘宝排行榜 V3 项目总结
yyfrankyy
0
150
Other Decks in Programming
See All in Programming
Vite+ Unified Toolchain for the Web
naokihaba
0
340
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
3
740
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2.3k
技術記事、AIに書かせるか、自分で書くか? 〜それでも私が自分の手で書く理由〜 / #QiitaConference
jnchito
2
1.5k
過去最大のMCPアップデート! 2026-07-28 RC版の謎に迫る
licux
6
390
The ROI of Quarkus for Spring Boot Applications
hollycummins
0
140
JavaDoc 再入門
nagise
1
410
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
560
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
1
300
New "Type" system on PicoRuby
pocke
1
1k
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
920
Language Server 使ってる? 〜VSCode と Zed の場合〜 / Are you using a Language Server? ~For VS Code and Zed~
handlename
0
800
Featured
See All Featured
Optimizing for Happiness
mojombo
378
71k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
200
So, you think you're a good person
axbom
PRO
2
2.1k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
1.1k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
740
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
270
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
How to train your dragon (web standard)
notwaldorf
97
6.7k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
540
Mobile First: as difficult as doing things right
swwweet
225
10k
Transcript
FtnApp 的缩略图实践 AyangXu
列表缩略图和预览大图 图片缓存策略(磁盘,内存) 耗时操作的应对(读写、压缩) 大图滑动的逐步调优 Agenda
两种缩略图的异同
列表缩略图 文件小(15-20k) 文件多(列表) 滑动的时候频繁读 高缓存命中
预览大图 文件大(200k+) 绘制耗时长 重用率低 内存控制要求更高
共同特点 平滑性要求高 多重检查:本地 ➜ 原图(压缩) ➜ 网络 过度状态(ICON / loadingView)
small loadThumbnail big QMCache thumb.db file original file web thumbnail
小图的缓存策略(磁盘) small loadThumbnail QMCache thumb.db original file web thumbnail
小图的缓存策略(磁盘) 全部小图保存到⼀一个 DB 启动的时候子线程加载(15k*100张) 滚动停止时,只更新 visibleCells 先更新内存,显示,再在后面更新 DB 不要在 cellForRowAtIndexPath
里做太多事情
图片缓存策略
小图的缓存策略(内存) 内存更新策略 缩略图只加不减 全部小图,包括默认的 ICON 都只读⼀一次
大图的缓存策略(内存) NSCache NSDiscardableContent / NSPurgeableData 不Copy Key,释放时机不可控 QMCache NSMutableArray w/
NSMutableDictionary 自定义 Capacity,多了就删
耗时操作的应对
QMCache thumb.db file original file web thumbnail 难点: 两种 IO
操作 两个网络操作 相互嵌套 本地 ➜ 原图 ➜ 网络
GCD VS OperationQueue GCD 保留作用域,线程池 不好控制并发任务,不好取消 NSOperationQueue w/ NSBlockOperation FIFO,封装了
GCD,可配置并发数,支持取消 保留还在队列里的 URL,避免重复的操作 快速滑动时,取消未开始的任务,优先留给当前页
[queue addOperation: [NSBlockOperation blockOperationWithBlock:^{ dispatch_async( dispatch_get_main_queue(), ^{/*UI*/}); }]]; dispatch_async( dispatch_get_global_queue(0,0),
^{ dispatch_async( dispatch_get_main_queue(),^{/*UI*/}); }); VS
大图滑动的逐步调优
大图滑动的基本实现
两层UIScrollView 1 2
⼀一次性准备ContentSize { numOfImages * (width + padding), height }
[previewImage renderMultipleImages: ^(int page, downloadImageCallback callback) { asyncLoadImage(page, ^(UIImage *image)
{ callback(image); }); } ]; 将读取逻辑扩展出去
评估工具 Core Animations Allocations Instruments
大图滑动 V1 图片和 loadingView 分开两个数组 未渲染部分用 [NSNull null] 占位,提前创建 好N个
loadingView 检查是否 [NSNull class] 来判定是否需要加 载 scrollViewDidEndDecelerating 时加载 每次加载时创建 view,加载过的不会释放
大图滑动 V1 FPS 10-15 不断创建新的 view,不断释放 在 scrollViewDidEndDecelerating 才加载,太 慢
进列表时间很长,初始化东西太多
大图滑动 V1.1 动态补充 loadingView 将绘制逻辑改到 scrollViewWillBeginDragging 缓存第二层的 zoomingScrollView
大图滑动 V1.1 进列表时间有所改善 所有第⼀一次翻动都很卡 FPS: 10-15 Cache 过的 view 不需重新创建
FPS: 20-30
大图滑动 V1.2 提前加载左右 N 页 判定是否到了 N 页,再进行加载 N =
5
大图滑动 V1.2 预加载左右 5 张,进列表时间又长了⼀一点 左右 5 张之内 FPS 30-40
第 6 张⼀一次性又要加载5张 FPS 10-20
大图滑动 V1.x zoomingScrollView 基本不可重用 大图缓存的命中率很低 每⼀一次绘制都需要遍历三个N长数组 图片,loadingView,zoomingScrollView 每次翻动的时间跟列表长度相关 O(N) 创建后不移出
view,subviews 越来越多
大图滑动 V2 不采用单独的 loadingView 数组和 [NSNull null] 用 zoomingScrollView 来引用
loadingView 跟 image View的缓存和回收 NSMutableSet 无序,NSObject 不重复 visiblePages / recyclePages
大图滑动 V2 scrollViewDidScroll 判定当前可见的页(<=2) 如果需要绘制,从 recyclePages 里 dequeue ⼀一个放到 visiblePages
回收不可见的页,从 visiblePages 里挪到 recyclePages 如果不需要绘制,什么都不做
大图滑动 V2 FPS 40-50 保持外层 UIScrollView 的 subviews,最多只 有两个 减少不断创建新
view 的开销 减少 scrollViewDidScroll 时的遍历开销 O(1)
进化路线 滑动时的 FPS 15 => 45 滑动时的遍历:O(n) => O(1) 内存增长:
view 的创建和回收: N => 2
Next? 大图内存没有尽快释放 [obj release] 只是引用-1,并没有马上释放 采用小图策略,DB 保存等比小图 ⼀一次加载到内存,内存只缓存小图 (20k *
100) 快速滑动时拉伸小图,模糊,但是快 scrollViewDidEndDecelerating 时绘制大图 view 不可见时马上清大图 image = nil;
And.. [NSURLConnection sendSynchronousRequest:returningResponse:error:] 所有网络数据都 load 到内存,并发下载三个, 内存涨了 10M (Oh my!)
对可能的大图片,异步 IO + 文件流
Thanks Q&A