Android——卡顿优化布局篇(含学习资料分享)_android 多次执行removeview 导致的性能问题

写在最后

在技术领域内,没有任何一门课程可以让你学完后一劳永逸,再好的课程也只能是“师傅领进门,修行靠个人”。“学无止境”这句话,在任何技术领域,都不只是良好的习惯,更是程序员和工程师们不被时代淘汰、获得更好机会和发展的必要前提。

如果你觉得自己学习效率低,缺乏正确的指导,可以一起学习交流!

加入我们吧!群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

CPU(中央处理器) :我们经常听到,是计算机的核心器件,多缓存多分支,适用于复杂的逻辑运算,主要负责Measure,Layout,Record,Execute的计算操作

GPU(图像处理器):我们通常说的显卡核心就是它了。用于结构单一的数据处理(擅长图形计算),主要负责Rasterization(栅格化)操作

谷歌官方对于流畅度的优化也是高度重视的,有界面渲染三核心Vsync、Triple Buffer和Choreographer。

为何是16ms/为何每秒60帧

android系统每隔16ms绘制一帧UI且要在16ms内完成,( 1秒 / 0.016帧每秒 = 62.5帧/秒 )差不多每秒更新60次。这是因为我们大脑和眼睛一般看24Fps的画面就已经是连续的运动了,看60Fps的画面更看不出端倪,但是60帧可以表达出更加绚丽多彩的内容。

一旦没及时绘制,就会出现掉帧问题,也就是常说的卡顿。这是因为绘制的东西太多的话,CPU、GPU处理不及时。

当然了,设备性能越好,处理能力越强,卡顿会越少,玩游戏的电脑配置高也是出于这方面考虑。

那么Android是如何把图像绘制到界面上的呢?

这就用到了上面的CPU/GPU。

GPU负责栅格化操作(Resterization),栅格化是绘制那些Button,Shape,Path,String,Bitmap等组件最基础的操作。它把那些组件拆分到不同的像素上进行显示。这是一个很“费时”的操作(相比人类时间只是眨眼的功夫),GPU的引入就是为了加快栅格化的操作。

CPU负责把UI组件计算成Polygons,Texture纹理,然后交给GPU进行栅格化渲染。流程如下:

为了能够使得App流畅,我们需要在每一帧16ms以内处理完所有的CPU与GPU计算,绘制,渲染等等操作。

有兴趣更深层学习的,可以去看看界面渲染容器DisplayList

😜什么是过度绘制

Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了N次。但是我们只能看到最上层的UI,这就会导致多层次的UI界面除最上层外对用户都是不可见的,这样就会浪费大量的CPU以及GPU资源,浪费可耻。

这就像我们在纸上固定区域不断图画,但是有最上层最接近你,其他层有个鬼用?

😜如何查看绘制维度

开发工具有Hierarchy View、Systrace、Track等

真机在开发者选项中有:调试GPU绘制、硬件层更新、GPU视图更新等等

😜界面优化

在编写Android布局时总会遇到这样或者那样的痛点,比如:

  • 1.有些布局的在很多页面都用到了,而且样式都一样,每次用到都要复制粘贴一大段,有没有办法可以复用呢?
  • 2.解决了1中的问题之后,发现复用的布局外面总要额外套上一层布局,要知道布局嵌套是会影响性能的呐;
  • 3.有些布局只有用到时才会显示,但是必须提前写好,虽然设置了为invisible或gone,还是多多少少会占用内存的。

首先第一点也是最重要的一点,在刚开始写布局的时候一定要提前想好和规划好,尽可能的减少层级的嵌套。往往越复杂的布局越臃肿,越容易被忽视进而出现性能问题,所以我们写布局就要知道一些技巧来展示布局

    1. 如果图片和文字在一起且文字不动态变的话,可以直接使用带文字的图片。
    1. 移除没用的布局和控件,假设添加个背景,尽可能在已经布局上放,减少只有背景功能的控件。
    1. 减少透明度的使用,假设:#55FFFFFF 和 #888888 颜色类似,建议使用后者,因为前者有Alpha,view需要至少绘制两次。
    1. 去掉多余的不可见颜色背景、图片等,只保留最上层用户可见即可
    1. 减少布局层次结构,避免多层嵌套推荐使用RelativeLayout、ConstraintLayout等父类布局
    1. 基本控件LinearLayout 性能比RelativeLayout高一些,要提前根据UI想好哪个布局更合适,要有的方式,对症下药。
    1. 自定义View尽可能只更新渲染局部区域,杜绝不断全部重绘。
    1. 推荐使用IDE自带的Lint或者阿里代码检查插件,对于标黄警告等提示重视起来,能改的就改。

除了以上,我们就要解决过度绘制,我们还可以使用抽象布局,它们分别是include、merge和ViewStub三个标签,现在我们就来认识认识它们吧。

Include应该是最常用的了,其翻译是“包含”、“包括”,最佳使用就是把相同代码抽离出来成一个独立的xml文件,当你在某个布局需要使用的时候直接include进来,这样一搞,很好地起到复用布局的效果。不仅可以极大地减少代码量,想要修改的话直接改这一个xml就行了。

它的两个主要属性:layout:必填属性, id属性;

我们还可以重写宽高、边距和可见性(visibility)这些布局属性。但是一定要注意,单单重写android:layout_height或者android:layout_width是不行,必须两个同时重写才起作用。

这些也能玩不不少花样。

Merge介绍

凡事都有利有弊include标签除了上面的优点,也有个问题就是布局嵌套。他必须有一个根布局,这也导致了最终布局嵌套层级可能多一层。

这时候又引出个新的标签标签,这次先说他的局限性:就是你需要提前明确要放到什么父布局中,然后提前设置好merge里面的控件位置。

优点也明显:他是消除多余层级的,标签必须作为根节点出现。不占用空间,他只是将子view“搬运”到你想嵌套的位置。

ViewStub

写布局的时候我们经常会遇到有些效果不必一直显示,需要动态的来设置invisible或gone,这无形中影响了页面加载速度。

Android提供的方案就是ViewStub,他是一个不可见的大小为0的视图,具有懒加载功能,存在于视图中,但只有设置setVisibility()和inflate()方法调用后才会渲染填充视图,能为初始化加载xml布局分散压力,就像负载均衡。

使用案例:进度条,加载网络失败,显示错误消息等等

它有以下三个重要属性:

android:layout:ViewStub需要填充的视图名称,为“R.layout.xx”的形式;

android:inflateId:重写被填充的视图的父布局id。

与include标签不同,ViewStub的android:id属性是设置ViewStub本身id的,而不是重写布局id,这一点可不要搞错了。另外,ViewStub还提供了OnInflateListener接口,用于监听布局是否已经加载了。

但是注意 viewStub.inflate();方法不能多次调用,否则抛出异常:

java.lang.IllegalStateException: ViewStubmusthaveanon-nullViewGroupviewParent

原因是ViewStub源码调用了removeViewInLayout()方法把自己从布局移除了。到这里我们就明白了,ViewStub在填充布局成功之后就会自我销毁,再次调用inflate()方法就会抛出IllegalStateException异常了。此时如果想要再次显示布局,可以调用setVisibility()方法。

还有一个大坑:viewStub.getVisibility()的值一直为0,所以用他来判断是否显示没作用。不要急,其实是setVisibility()方法实际上在设置内部视图的可见性,而不是ViewStub本身。

😜硬件加速原理

相信经常看到有的文章说开启硬件加速解决卡的问题,但硬件加速是什么呢?

硬件加速的主要原理是通多底层逻辑,将CPU不擅长的图形计算转换成GPU专用指令,让更擅长图形计算的GPU来完成渲染。

硬件加速过程中包含两个步骤 :

构建阶段 : 遍历所有视图,将需要绘制的操作缓存下来,交给单独的Render线程使用GPU进行硬件加速渲染。(这一阶段在主线程中使用CPU构建)

最后

下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。希望能够帮助到大家提升技术

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值