Android App卡顿分析和优化

流畅度就是衡量APP卡顿程度的指标。一个APP的开发需要先经过work,right,最后才是fast。优化的前提是基于业务,一定要根据业务去谈优化。


CPU耗时/消耗:

界面的性能取决于UI渲染性能,布局层次过深、无效的绘制、布局内容繁杂冗余不规范、自定义view中onDraw方法设计复杂运算都会导致界面卡顿,影响UI渲染性能

工具和布局

检测工具:Android Monitor(CPU)

 Android Device Monitor is a standalone tool that provides a UI for several Android app debugging and analysis tools. 
 However, most components of the Android Device Monitor are deprecated in favor of updated tools available in Android Studio 3.0 and higher. The table below helps you decide which developer tools you should use.
 可以通过以下方法打开:

布局优化

善于使用Tag,布局模块化:

1.使用标签来重用布局

2.使用标签来减少view的层级,主要解决或者自定义组合ViewGroup导致的冗余层级问题

3.使用标签代替setVisiblity,按需载入,只有在布局文件重用时才加载,再inflate

减少布局层级和复杂度,减少overdraw:

1.尽量不要嵌套使用RelativeLayout

2.尽量不要在嵌套的LinearLayout中使用weight属性,该属性会减慢measure的速度

3.去掉多余的背景颜色,去掉不必要的父布局

4.尽量是Layout宽而浅,而不是窄而深,以减少view树的层级为主

ListView优化:

1.contentView复用

2.避免重复调用findViewById(holder)

3.优化item布局

4.分页加载

优雅布局

1.代码格式化布局,删除注释

2.避免硬编码

3.不使用废弃关键字,如dip、fill_parent等

4.尽可能消除warning,单词编写错误等

复杂运算

在UI线程中进行复杂的运算可能直接导致ANR

GPU耗时消耗

过度绘制,也是属于UI布局,设计GPU渲染,其含义是屏幕上的某个像素点在同一帧中被绘制多次,负责的UI层级叠加,太多view叠加或者inflate时间过长都会导致overdraw

检测工具:设置--开发者选项--调试GPU过度绘制中打开显示过度绘制区域,会看到多种颜色,分别表示过度绘制的次数,从好到差依次是:蓝>绿>淡红>红,对应1x,2x,3x,4x绘制

优化建议

1.移除window中默认的background,具体代码:getWindow().setBackgroundDrawableResource(android.R.color.transparent);

2.移除布局中冗余的background

3.不需要显示的布局要及时隐藏(如层叠UI中,被遮挡布局等)

4.按需显示占位背景图片,减少Drawable复杂Shape使用

5.自定义view中使用clipRect和quickReject来屏蔽哪些重叠画面中被遮盖或者不需要View的绘制,跳过指定区域View的绘制

6.自定义view中慎用onDraw方法,减少多次调用

7.Show GPU overdraw中将overdraw控制在2x

内存相关

GC

频繁的GC会导致卡顿,原因是执行GC的时候任何其他线程都会暂停,等待GC执行完后再继续

线程相关

ANR应用无响应

当在UI线程中做了阻塞耗时操作或者在超时时间里对输入事件或特定操作没有处理完时会发生ANR,常见场景及时间限制:

service生命周期函数,20秒

broadcast receiver接收前台优先级广播函数,10秒

broadcast receiver接收后台优先级广播函数,60秒

影响进程启动的函数,10秒

影响输入事件处理的函数,5秒

影响Activity切换的函数,2秒

后面两种场景因为涉及到用户交互,会弹出系统对话框,常见的ANR原因及优化建议:

1.主线程阻塞,挂起,死循环

2.其他线程CPU占用率高,使得主线程无法抢到CPU时间片

3.多进程间通信,当前进程超时间未收到其他进程反馈,等待超时

4.其他进程CPU占用率高,使得当前进程无法抢到CPU时间片

主要就是主线程阻塞和CPU满负荷,可以通过开启子线程异步来处理耗时和IO阻塞任务,不做任何阻塞主线程的操作,另外内存不够用了也可能引起ANR,这就涉及内存优化

内存性能优化

Android本身既支持Java,又支持C++,框架上又基于Linux上承接Android Framework。

Java内存机制:

Java内存区域分为:方法区,堆,栈和程序计数器。

方法区:默认值最大容量64MB,存放类的结构(方法和属性)、静态成员等,运行时的常量池,被所有线程共享的内存区域

堆(Heap):默认最大容量64MB,存放对象持有的数据,同时保持对原类的引用,被所有线程共享的内存区域

栈(Stack):分为虚拟机栈(JVM Stacks)和本地方法栈(Native Method Stacks)。虚拟机栈是为Java方法服务,用于存储局部变量表、动态链接、操作数、方法出口等信息,有两种可能的Java异常StackOverFlowError和OutOfMemoryError;本地方法栈是为Native方法服务,默认最大容量1MB,属于线程私有内存区域

程序计数器:可以看做是当前线程执行字节码的行号指示器,位于CPU中,程序不能直接对其操作,每个线程都有独立的程序计数器,属于线程私有内存区域

GC(Garbage Collection/Collector):垃圾回收/回收器。用于分配内存,确保被引用对象保留在内存中,以及回收不存在引用关系的对象内存

C/C++内存机制:

C/C++内存空间由栈区、堆区、全局/静态存储区、常量存储区和程序代码区组成

栈区:存储执行函数的参数和局部变量等,容量有限,效率很高,由程序自动分配和释放

堆区:由程序手动分配和释放。C中采用malloc/free,C++中采用new/delete进行分配和释放,堆大小无限制,由OS内存空间大小决定

全局/静态存储区:存放全局变量和静态变量的区域

常量存储区:存放常量的区域,不允许修改

程序代码区:存放程序的二进制代码

Android内存管理

Android中包括Native和Java两类进程,Native进程基于C/C++实现,是不包含Davlik实例的进程;Java进程基于Java语言,是运行在Davlik/ART虚拟机上的进程。Android中每个APP默认情况下是运行在独立的VM空间

APP内存限制:不同的手机厂商的APP内存限制不同,存放在system/build.prop中。可以在adb shell环境中采用cat system/build.prop 命令查看

APP应用切换:Android系统不会在用户切换不同应用时做内存交换的操作,而是会把那些不在前台可见的进程放到LRU缓存中,主要便于在应用再次切换回时快速响应

你可能感兴趣的:(android,ui)