android要不要优化:用这三个方法手把手带你了解何为
android要不要优化:用这三个方法手把手带你了解何为绘制过程是 CPU 准备数据,通过 Driver 层把数据交给 CPU 渲染;其中 CPU 主要负责 Measure,Layout,Record,Execute 的数据计算工作,GPU 负责 Rasterization (栅格化)渲染Android 的显示过程可以简单概括为:应用层把经过测量,布局,绘制后的 surface 缓存数据,通过 SurfaceFlinger 把数据显示到屏幕上;应用层负责绘制,系统层负责渲染,通过进程间通信把应用层需要绘制的数据传递到系统层这一点可以从我们 MainActivity 默认布局就可以看出,默认是 RelativeLayout,因为可以通过扁平的 RelativeLayout 降低 LinearLayout 嵌套所产生布局树的层级一般情况下用 LinearLayout 的时候总会比 RelativeLayout 多一个 View 的层级;而每次往应用
Android 性能优化的三个方法布局优化布局优化的思想很简单,就是尽量减少布局文件的层级,布局中的层级少了,这就意味着 Android 绘制时的工作量少了,那么程序的性能自然就高了
那么如何进行布局优化呢?有以下两点:
- 首先删除布局中无用的看控件和层级,其次有选择地使用性能较低的 ViewGroup,比如 RelativeLayout
- 可以采用标签 ViewStub ;标签主要用于布局重用,标签一般配合标签使用,它可以降低减少布局的层级,而 ViewStub 则提供了按需加载的功能
布局的优化其实说白了就是减少层级,越简单越好,减少 overdraw,就能更好的突出性能
下面介绍几种布局优化的方式:
首先是善用相对布局 Relativelayout- 在 RelativeLayout 和 LinearLayout 同时能够满足需求时,尽量使用 RelativeLayout
这一点可以从我们 MainActivity 默认布局就可以看出,默认是 RelativeLayout,因为可以通过扁平的 RelativeLayout 降低 LinearLayout 嵌套所产生布局树的层级
- Android 提供了几种方便的布局管理器,大多数时候,你只需要这些布局的一部分基本特性去实现 UI
一般情况下用 LinearLayout 的时候总会比 RelativeLayout 多一个 View 的层级;而每次往应用里面增加一个View,或者增加一个布局管理器的时候,都会增加运行时对系统的消耗,因此这样就会导致界面初始化、布局、绘制的过程变慢
绘制优化绘制优化是指 View 的 onDraw 方法要避免执行大量的操作,主要体现在两个方面:
- onDraw 中不要创建新的局部对象,这是因为 onDraw 方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统会更频繁 gc,降低程序的执行效率
- onDraw 方法中不要做耗时的任务,也不能执行成千上万次的循环操作;尽管每次循环都很轻量级,但是大量的循环仍然十分抢占 CPU 的时间片,这会造成 View 的绘制过程很不流畅
Android 的显示过程可以简单概括为:应用层把经过测量,布局,绘制后的 surface 缓存数据,通过 SurfaceFlinger 把数据显示到屏幕上;应用层负责绘制,系统层负责渲染,通过进程间通信把应用层需要绘制的数据传递到系统层
应用层:- Measure:用深度优先原则递归得到所有视图的宽高
- Layout:用深度优先原则递归得到所有视图的位置
- Draw:支持两种绘制:软件绘制(CPU)和硬件加速(GPU),硬件加速 Android3.0 开始支持
- 硬件加速缺点:耗电,兼容问题,内存大
- Android 显示系统使用了匿名共享内存:SharedClient,每个应用和 SurfaceFlinger 之间都会创建一个 SharedClient,最多可以创建31个 SharedBufferStack 集合,每个 Surface 都对应一个 SharedBufferStack,也就是一个 window
- 应用层绘制到缓存区,SurfaceFlinger 把缓存区数据渲染到屏幕,由于两个进程不同使用了 Android 的匿名共享内存 SharedClient
绘制过程是 CPU 准备数据,通过 Driver 层把数据交给 CPU 渲染;其中 CPU 主要负责 Measure,Layout,Record,Execute 的数据计算工作,GPU 负责 Rasterization (栅格化)渲染
CPU 和 GPU 通信是通过图形驱动层(Graphics Driver)来连接两部分;图形驱动维护了一个队列 CPU 把 display list 添加到队列中,GPU 从这个队列中取出数据进行绘制,最终显示出来
内存优化内存简介:
RAM(random access memory)随机存取存储器;说白了就是内存
一般 Java 在内存分配时会涉及到以下区域:- 寄存器(Registers):速度最快的存储场所,因为寄存器位于处理器内部,我们在程序中无法控制
- 栈(Stack):存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中
- 堆(Heap):堆内存用来存放由 new 创建的对象和数组;在堆中分配的内存,由Java虚拟机的自动垃圾回收器(GC)来管理
- 静态域(static field): 静态存储区域就是指在固定的位置存放应用程序运行时一直存在的数据, Java 在内存中专门划分了一个静态存储区域来管理一些特殊的数据变量如静态的数据变量
- 常量池(constant pool):虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string integer和floating point 常量)和对其他类型,字段和方法的符号引用
- 非RAM存储:硬盘等永久存储空间
内存泄露在开发过程中是一个需要重视的问题,内存优化分为两个方面:一方面是在开发过程中避免写出有内存泄露的代码,另一方面是通过一些分析工具比如MAT来找出潜在的内存泄露继而解决
内存的优化:内存优化分为 内存泄漏的优化,bitmap 的优化,ListView的优化,和线程优化
- 我们写的单例模式(咱们通常引用的 Activity 的上下文,单例模式的类是静态类,当 Activity 销毁的时候,这个静态类还保持着 Activity 的引用,这就造成 GC 无法回收从而造成内存泄漏)
解决方法:把咱写的 App 中的 Activity 上下文,在 OnPuse()方法里面将其致 null 即可
- Bitmap 对图片的一个压缩的优化,主要就是通过 Options 计算出二次采样率然后设置 inSampleSize 属性按几倍进行压缩,从而得到图片的一个优化
- 对 Bitmap "对象"的优化使用 inBitmap 的主要作用是复用之前bitmap在内存中申请的内存,其实这是对象池的原理,以解决对象频繁创建再回收的效率问题。(inBitmap只能在3.0以后使用)
- 属性动画导致内存泄漏 (在android3.0 Google 提供了属性动画),动画播放完之后, 尽管我们看不到动画的播放效果,但在内部处于无限循环播放的状态
解决办法:解决方法就是在 onDestory 或动画结束监听中调用 animator.cancle()
- 集合对象没有清理导致的内存泄漏 我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,如果没有把它的引用从集合中清理掉,这样这个集合就会越来越大
资源对象没有手动关闭或处理,资源性对象(BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap)导致的内存泄漏
今天有关于 Android 的性能优化的相关内容就介绍到这里了,有需要了解更多关于 Android 性能优化 的相关资讯;可以私信发送 "性能" ,即可获取一份 Android 性能优化学习手册,以便大家能够更好的学习 性能优化
内容展示如下:
崩溃优化- 崩溃的收集
- ANR
- 应用退出
- 崩溃处理
- 崩溃现场
- 崩溃分析
- 系统崩溃
- 网络指标
- 用户体验
- 网络监控
- Network Monitor
- Charles 抓包工具
- 优化 DNS 解析
- 连接池复用
- 数据压缩
- 弱网优化
- 网络安全
- Android 存储方式
- SharedPrefence
- 多进程问题 -> mmkv
- 已经有 xml/json,为什么要用 protobuf
- 项目中使用 protobuf
- 语言规范
- 字段约束
- 编码协议
对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们
技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面
最后祝各位开发者早日精通性能优化 ,攀登上更高的高峰