iOS - TABAnimated骨架屏缓存策略

前言

使用TABAnimated集成骨架屏的开发者,大概都知道其原理是基于原视图映射生成骨架层,在细节上不满意的地方可以通过预处理回调进行异步调整。

  • 本文内容:TABAnimated的缓存策略
  • 使用TABAnimated的开发者,此文档建议阅读

TABAnimated缓存的是什么?

缓存的是通过映射机制生成的骨架屏单元管理对象TABComponentManager
对该对象使用一个plist文件来解释。同时,通过计数的方式,逐渐筛选出该用户经常加载的骨架屏,提高缓存命中率。

TABAnimated缓存功能有什么作用?

  • 相同版本的代码,避开了重复使用映射机制
  • 避开了映射采用的递归操作,降低了CPU峰值,提高系统性能
  • 省去部分场景的视图预填充成本及其他耗时操作,稳定性得到有效提升
  • 预处理回调需要重新调整CALayer的部分值,有效降低GPU绘制成本

性能评测

  • 评测工具:Instruments
  • 评测环境:单线程
  • 评测机型:iPhone 6s
image

分析

其实,从峰值数据来看,GPU、CPU的数值本身并不高,缓存功能也并没有将他们的峰值降低很多,但是我为什么还要引入缓存策略呢?

答:

  1. 缓存策略更多地是优化了映射机制的耗时。对于CPU性能不高的设备,在极端的情况下,不能在下一次Vsyc信号来临时,将骨架屏的数据计算好并交给GPU处理,此时造成掉帧情况。

当然,掉帧是非常极端的情况。
例如:iPhone6 + 自适应高度 + 不规范的页面布局

  1. 映射机制,是基于当前开发好的视图。如果我的App打包上线了(除了热更新),那么此时骨架屏的映射结果也已经确定了,那么我还有必要每次都去映射一遍吗?

答案显然是不需要的。

TABAnimated采取的是:把映射结果存储在本地plist文件(大小约4kb)。唯一注意的是,TABAnimated会读取你的App版本,当你的App版本发生了变动,会重新映射一次。

正文目录

  • 集成注意
  • 缓存流程
  • 存储结构
  • 线程处理
  • 特殊场景

一、集成注意

考虑到有些用户主要关注对后续使用会有什么影响,所以该点放到第一位。

集成只强调一点!!!也是最重要的一点,反复强调!!!

TABAnimated新增closeCache属性。

  • debug 环境下,默认关闭缓存功能(为了方便通过预处理回调调试)
  • release 环境下,默认开启缓存功能
  • 如果你想在 debug 环境下测试缓存功能,可以强制置为NO。但是这个时候请注意,预处理回调再做修改,无效!
  • 如果你始终都不想使用缓存功能,可以强制置为YES

二、缓存流程

缓存策略流程图

下面是流程图中相关说明:

1. 全局字典

App在启动时(图左侧),会预读取对于该用户来说加载次数最多的一部分数据到全局字典。

全局字典内容:key为plist文件名,value为解释TABAnimatedManager对象的plist文件内容

2. plist文件名

plist文件名用于唯一标识骨架屏管理对象。

  • 起初,仅根据className唯一标识。但是有些class会在多个地方,不同adjustBlock中出现,即这种方式无法唯一定位某个骨架屏视图。

  • 最好的方式是将原视图的className+预处理回调字符串化(学过java的应该都用过toString()吧),但是如果回调处理的东西过多,会浪费大量资源。

  • 于是,采取的方案是:在启动动画后,获取当前控制视图(control view)的UIViewController的className,
    将其合并。

fileName

3. 描述"加载次数最多"、loadCount?

为了描述加载次数最多,引入了TABAnimatedCacheModel,
TABAnimatedCacheModel同样是用一个plist文件解释。与TABAnimatedManager同名

  • 一个描述TABAnimatedCacheModel的plist文件,大小约为300bytes
  • 一个描述TABAnimatedManager的plist文件,大小约为3kb

loadCount字段作用:
App启动后,读取沙盒中所有的TABCacheModel文件,根据loadCount降序排列TABCacheModel数组,并加载数组中前n个TABComponentManager到内存中,存储方式是全局字典。(n默认为20)

loadCount更新机制:
启动动画后,在下一次runloop执行时,放到串行队列中。

4. 为什么要通过TABAnimatedCacheModel计数,而不是TABAnimatedManager自计数?

一个用于解释TABAnimatedManager的plist文件大概是4kb,如果仅仅为了更新一个字段频繁写入,很明显浪费资源。
TABAnimatedCacheModel仅需要300bytes。

5. 版本控制

如果开发者在待发布的版本,对某个已经在沙盒中存在的plist文件,其对应视图和预处理回调做了修改,此时需要重新写入。所以在读取缓存对象前,需要进行版本校对,如果不一致,需要重新使用映射机制。

太长不看😶😶???

image

三、存储结构

image
  • 默认生成文件夹TABAnimated
  • 默认在TABAnimated文件夹里生成2个文件夹cacheModelcacheManager
  • cacheModel用于存储TABAnimatedCacheModel对象,该对象只有2个字段,一个用于索引cacheManager,一个用于描述cacheManager的加载次数,即loadCount
  • cacheManager存储的就是能够解释骨架屏的骨架管理对象

存储路径:沙盒根目录/Document/TABAnimated/

四、线程处理

  • 默认创建一个串行队列,调度plist文件写入、更新任务。
  • 默认开辟一个常驻的子线程。该线程主要负责执行plist文件写入、更新任务。通过添加NSMachPort端口保证该线程的runLoop不会退出。
  • 当加载了新的(沙盒中没有的)骨架对象,该骨架对象会立即写入全局字典(即内存中),但是并不急着写入沙盒,会将该任务交由已经创建好的串行队列调度。

五、特殊场景

如果你的列表数据,需要针对每一个row做特殊处理。
框架内部重写了getter方法,检测到这种情况后,每次都会强制使用映射机制。

当然后续会继续探索更好的处理方式,目前先这样处理,不会存在太大的问题~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,094评论 1 32
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,292评论 0 9
  • 0x00 背景 复杂网络一直是个很有意思的领域,虽然它现在没有深度学习那么火爆,但这么多年来一直在稳步的发展,更是...
    bindog阅读 890评论 0 3
  • 真的很感谢王老师,也感谢自己坚持选择了水彩基础课。回想第一次绘画小白的尝试,颤颤巍巍地下笔画了个彭彭鱼的闭眼照,现...
    光目言阅读 289评论 1 1
  • 平湖落秋月,高峡降初雪, 默默无声息,爽爽有前约。 雪花贴水面,姐妹情切切, 都是同渊生,今此共佳节。
    云逸1108阅读 307评论 0 1