尾声
开发是需要一定的基础的,我是08年开始进入Android这行的,在这期间经历了Android的鼎盛时期,和所谓的Android”凉了“。中间当然也有着,不可说的心酸,看着身边朋友,同事一个个转前端,换行业,其实当时我的心也有过犹豫,但是我还是坚持下来了,这次的疫情就是一个好的机会,大浪淘沙,优胜劣汰。再等等,说不定下一个黄金浪潮就被你等到了。
- 330页 PDF Android核心笔记
- 几十套阿里 、字节跳动、腾讯、华为、美团等公司2020年的面试题
- PDF和思维脑图,包含知识脉络 + 诸多细节
- Android进阶系统学习视频
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
问题:cell对多张图片用maskToBounds进行圆角处理的话,帧数下降很快,容易造成卡顿。
原因:一次mask发生了两次离屏渲染和一次主屏渲染。即使忽略昂贵的上下文切换,一次mask需要渲染三次才能在屏幕上显示,这已经是普通视图显示3陪耗时,若再加上下文环境切换,一次mask就是普通渲染的30倍以上耗时操作。问我这个30倍以上这个数据怎么的出来的?当我在cell的UIImageView的实例增加到150个,并去掉圆角的时候,帧数才跌至28帧每秒。虽然不是甚准确,但至少反映mask这个耗时是无mask操作的耗时的数十倍的。
Off-Screen Rendering(离屏渲染)
指的是GPU在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作。由上面的一个结论视图和圆角的大小对帧率并没有什么卵影响,数量才是伤害的核心输出啊。可以知道离屏渲染耗时是发生在离屏这个动作上面,而不是渲染。为什么离屏这么耗时?原因主要有创建缓冲区和上下文切换。创建新的缓冲区代价都不算大,付出最大代价的是上下文切换。
上下文切换
上下文切换,不管是在GPU渲染过程中,还是一直所熟悉的进程切换,上下文切换在哪里都是一个相当耗时的操作。首先我要保存当前屏幕渲染环境,然后切换到一个新的绘制环境,申请绘制资源,初始化环境,然后开始一个绘制,绘制完毕后销毁这个绘制环境,如需要切换到On-Screen Rendering或者再开始一个新的离屏渲染重复之前的操作。 下图描述了一次mask的渲染操作。
构思:不使用或尽量少使用maskToBounds进行圆角处理
方案:
1、缓存视图渲染内容
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
这样大部分情况下可以马上挽救你的帧数在55帧每秒以上。shouldRasterize = YES可以使视图渲染内容被缓存起来,下次绘制的时候可以直接显示缓存,当然要在视图内容不改变的情况下。
2、预先生成圆角图片
采取预先生成圆角图片,并缓存起来这个方法才是比较好的手段。预处理圆角图片可以在后台处理,处理完毕后缓存起来,再在主线程显示,这就避免了不必要的离屏渲染了。
3、镂空圆形图片覆盖
此方法可以实现圆形头像效果,这个也是极为高效的方法。缺点就是对视图的背景有要求,单色背景效果就最为理想。
4、 Core Graphics API 绘制圆角
在willDisplayCell的方法里面我们把 cell的背景设置成透明,然后自定义 UIView 做为 cell 的 backgroundView,那如果需要选中状态的话,还需要再自定义一个 UIView 做为 cell 的 selectedBackgroundView,通过 Core Graphics API 来实现 UIView 图层圆角的绘制。
实操的时候,这里有几篇文章值得借鉴:
补充:UILabel实现圆角
1、不设置背景色(backgroundColor)类型:只设置borderWidth、borderColor的label,直接设置cornerRadius,不需要设置masksToBounds = YES,就可以实现圆角功能。
2、需要设置背景色(backgroundColor)类型:直接设置cornerRadius是不能正常显示圆角的,原因是:UILabel设置backgroundColor的行为,不再是设定layer的背景色而是为contents设置背景色。所以解决方式是我们不去设置label的backgroundColor,而是直接设置label.layer.backgroundColor,这样就可以实现单独设置cornerRadius,显示圆角的效果。代码:
UILabel *tagLabel = [UILabel new];
tagLabel.text = @"减";
tagLabel.textColor = [UIColor whiteColor];
tagLabel.font = [UIFont systemFontOfSize:12];
tagLabel.layer.backgroundColor = [UIColor greenColor].CGColor;
tagLabel.layer.cornerRadius = 2;
==========================================================================
问题:subview层级太复杂,给cell在绘制时添加很大的负担
原因:层级太复杂,需要做大量透明处理。
构思:手动绘制视图提升流畅性。将一些相对重复性很大的视图选择使用CoreText和CoreGraphic技术直接绘制在一个视图上,减少视图的层级。
实操细节分析:
1、手动绘制方法,不是直接子类化 UITableViewCell,然后覆盖 drawRect: 方法,这样你会得到一个大黑块!因为 cell 中不是只有一个 content view。如果不了解 cell 的层次结构,可以用 Reveal 去看下。
2、绘制 cell 不建议使用 UIView,而是用 CALayer。 UIView 的绘制是建立在 CoreGraphic 上的,使用的是 CPU。CALayer 使用的是 Core Animation,CPU,GPU 通吃,由系统决定使用哪个。View的绘制使用的是自下向上的一层一层的绘制,然后渲染。Layer处理的是 Texure,利用 GPU 的 Texture Cache 和独立的浮点数计算单元加速纹理的处理。
3、GPU不喜欢透明,所以所有的绘图一定要弄成不透明,对于圆角和阴影这些的可以截个伪透明的小图然后绘制上去。在layer的回调里一定也只做绘图,不做计算!
实操借鉴:CoreText实现图文混排系列,进一步学习中。
============================================================================
问题: 图片通过contentMode处理显示,对tableview滚动速度同样会造成影响。
原因:图片变形需要对图片做 transform ,每次压缩图片都要对图片乘以一个变换矩阵,如果显示的图片很多,这个计算量是不同忽视的。
构思方案:
1、从网络下载图片后先根据需要显示的图片大小切/压缩成合适大小的图,每次只显示处理过大小的图片,当查看大图时在显示大图。
2、服务器直接返回预处理好的小图和大图以及对应的尺寸最好。
实操:
1、图片剪切压缩集成。
2、后台配合。
实操借鉴:
=============================================================================
问题:当TableView快速滚动时,仍然会出现加载跟不上占用系统资源,导致卡顿。
原因: 当TableView的cell中图片很多时,快速滚动页面,使用SDWebImage加载图片虽然是异步过程,但是仍然十分占用系统资源。
构思:快速滚动或滚动时,图片异步加载处理。
方案:
1、TableView滚动的时候不去加载未加载过的图片,停止滚动后再从网络加载(做好监听判断处理)。
2、TableView快速滚动的时候(做好监听判断处理)不加载未加载过的图片,当滚动速度小于某个区间值(不管是拖动中还是没有拖动,不管是加速还是减速中)的时候再从网络加载未加载过的图片。
注:已经加载过得图片,无论什么时候都加载该图片(因为SDWebImage会将加载过得图片缓存下来,再次加载的时候从缓存中取,这样就不用开辟线程下载图片了)
方案分析:
尾声
在我的博客上很多朋友都在给我留言,需要一些系统的面试高频题目。之前说过我的复习范围无非是个人技术博客还有整理的笔记,考虑到笔记是手写版不利于保存,所以打算重新整理并放到网上,时间原因这里先列出面试问题,题解详见:
展示学习笔记
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!