ftnapp 的缩略图实践

36
FtnApp 的缩略图实践 AyangXu

Upload: frank-xu

Post on 03-Jul-2015

775 views

Category:

Technology


4 download

TRANSCRIPT

Page 1: FtnApp 的缩略图实践

FtnApp 的缩略图实践AyangXu

Page 2: FtnApp 的缩略图实践

列表缩略图和预览大图

图片缓存策略(磁盘,内存)

耗时操作的应对(读写、压缩)

大图滑动的逐步调优

Agenda

Page 3: FtnApp 的缩略图实践

两种缩略图的异同

Page 4: FtnApp 的缩略图实践

列表缩略图

文件小(15-20k)

文件多(列表)

滑动的时候频繁读

高缓存命中

Page 5: FtnApp 的缩略图实践

预览大图

文件大(200k+)

绘制耗时长

重用率低

内存控制要求更高

Page 6: FtnApp 的缩略图实践

共同特点

平滑性要求高

多重检查:本地 ➜ 原图(压缩) ➜ 网络

过度状态(ICON / loadingView)

Page 7: FtnApp 的缩略图实践

small

loadThumbnail

big

QMCache

thumb.db file

original file

web thumbnail

����

���

����

Page 8: FtnApp 的缩略图实践

小图的缓存策略(磁盘)

small

loadThumbnail

QMCache

thumb.db

original file

web thumbnail

Page 9: FtnApp 的缩略图实践

小图的缓存策略(磁盘)

全部小图保存到⼀一个 DB

启动的时候子线程加载(15k*100张)

滚动停止时,只更新 visibleCells

先更新内存,显示,再在后面更新 DB

不要在 cellForRowAtIndexPath 里做太多事情

Page 10: FtnApp 的缩略图实践

图片缓存策略

Page 11: FtnApp 的缩略图实践

小图的缓存策略(内存)

内存更新策略

缩略图只加不减

全部小图,包括默认的 ICON 都只读⼀一次

Page 12: FtnApp 的缩略图实践

大图的缓存策略(内存)

NSCache

NSDiscardableContent / NSPurgeableData

不Copy Key,释放时机不可控

QMCache

NSMutableArray w/ NSMutableDictionary

自定义 Capacity,多了就删

Page 13: FtnApp 的缩略图实践

耗时操作的应对

Page 14: FtnApp 的缩略图实践

QMCache

thumb.db file

original file

web thumbnail

难点:

两种 IO 操作

两个网络操作

相互嵌套

本地 ➜ 原图 ➜ 网络

Page 15: FtnApp 的缩略图实践

GCD VS OperationQueue

GCD

保留作用域,线程池

不好控制并发任务,不好取消

NSOperationQueue w/ NSBlockOperation

FIFO,封装了 GCD,可配置并发数,支持取消

保留还在队列里的 URL,避免重复的操作

快速滑动时,取消未开始的任务,优先留给当前页

Page 16: FtnApp 的缩略图实践

[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

Page 17: FtnApp 的缩略图实践

大图滑动的逐步调优

Page 18: FtnApp 的缩略图实践

大图滑动的基本实现

Page 19: FtnApp 的缩略图实践

两层UIScrollView

1

2

Page 20: FtnApp 的缩略图实践

⼀一次性准备ContentSize

{ numOfImages * (width + padding), height }

Page 21: FtnApp 的缩略图实践

[previewImage renderMultipleImages:^(int page, downloadImageCallback callback) {asyncLoadImage(page, ^(UIImage *image) {callback(image);

});}

];

将读取逻辑扩展出去

Page 22: FtnApp 的缩略图实践

评估工具

Core Animations Allocations

Instruments

Page 23: FtnApp 的缩略图实践

大图滑动 V1

图片和 loadingView 分开两个数组

未渲染部分用 [NSNull null] 占位,提前创建好N个 loadingView

检查是否 [NSNull class] 来判定是否需要加载

scrollViewDidEndDecelerating 时加载

每次加载时创建 view,加载过的不会释放

Page 24: FtnApp 的缩略图实践

大图滑动 V1

FPS 10-15

不断创建新的 view,不断释放

在 scrollViewDidEndDecelerating 才加载,太慢

进列表时间很长,初始化东西太多

Page 25: FtnApp 的缩略图实践

大图滑动 V1.1

动态补充 loadingView

将绘制逻辑改到 scrollViewWillBeginDragging

缓存第二层的 zoomingScrollView

Page 26: FtnApp 的缩略图实践

大图滑动 V1.1

进列表时间有所改善

所有第⼀一次翻动都很卡 FPS: 10-15

Cache 过的 view 不需重新创建 FPS: 20-30

Page 27: FtnApp 的缩略图实践

大图滑动 V1.2

提前加载左右 N 页

判定是否到了 N 页,再进行加载

N = 5

Page 28: FtnApp 的缩略图实践

大图滑动 V1.2

预加载左右 5 张,进列表时间又长了⼀一点

左右 5 张之内 FPS 30-40

第 6 张⼀一次性又要加载5张 FPS 10-20

Page 29: FtnApp 的缩略图实践

大图滑动 V1.x

zoomingScrollView 基本不可重用

大图缓存的命中率很低

每⼀一次绘制都需要遍历三个N长数组

图片,loadingView,zoomingScrollView

每次翻动的时间跟列表长度相关 O(N)

创建后不移出 view,subviews 越来越多

Page 30: FtnApp 的缩略图实践

大图滑动 V2

不采用单独的 loadingView 数组和 [NSNull null]

用 zoomingScrollView 来引用 loadingView 跟 image

View的缓存和回收

NSMutableSet

无序,NSObject 不重复

visiblePages / recyclePages

Page 31: FtnApp 的缩略图实践

大图滑动 V2

scrollViewDidScroll

判定当前可见的页(<=2)

如果需要绘制,从 recyclePages 里 dequeue ⼀一个放到 visiblePages

回收不可见的页,从 visiblePages 里挪到 recyclePages

如果不需要绘制,什么都不做

Page 32: FtnApp 的缩略图实践

大图滑动 V2

FPS 40-50

保持外层 UIScrollView 的 subviews,最多只有两个

减少不断创建新 view 的开销

减少 scrollViewDidScroll 时的遍历开销 O(1)

Page 33: FtnApp 的缩略图实践

进化路线

滑动时的 FPS 15 => 45

滑动时的遍历:O(n) => O(1)

内存增长:

view 的创建和回收: N => 2

Page 34: FtnApp 的缩略图实践

Next?

大图内存没有尽快释放

[obj release] 只是引用-1,并没有马上释放

采用小图策略,DB 保存等比小图

⼀一次加载到内存,内存只缓存小图 (20k * 100)

快速滑动时拉伸小图,模糊,但是快

scrollViewDidEndDecelerating 时绘制大图

view 不可见时马上清大图 image = nil;

Page 35: FtnApp 的缩略图实践

And..

[NSURLConnection sendSynchronousRequest:returningResponse:error:]

所有网络数据都 load 到内存,并发下载三个,内存涨了 10M (Oh my!)

对可能的大图片,异步 IO + 文件流

Page 36: FtnApp 的缩略图实践

ThanksQ&A