一、布局优化
1- UI渲染机制
系统通过VSYNC信号触发对UI的渲染、重绘,其间隔时间是16ms。这个16ms其实就是1000ms显示60帧画面的单位时间。如果不能在16ms内完成绘制,那么就会造成丢帧现象。会在下个信号才开始绘制(2*16ms)—导致卡顿
UI渲染时间工具
开发者选项
,选择Profile GPU Rendering
,并选中On screen as bars
的选项,这时候显示一些条形图。
柱状线 | |
---|---|
蓝色 | 绘制Display List时间 |
红色 | OpenGL渲染Display List所需要的时间 |
黄色 | CPU等待GPU处理的时间 |
- 蓝色为
VSYNC
时间 16ms,需要尽量都控制在绿线
之下
2- 避免Overdraw
过度绘制
例如:先绘制Activity的背景,再给布局绘制了重叠的背景。
检查工具Enable GPU OverDraw
3- 优化布局层级
- 降低View树的高度
对View的测量、布局、绘制,都是对View树进行遍历。
API文档建议View树高度不宜超过10层。
谷歌将XML文件默认根布局从
LinearLayout
替换成了RelativeLayout
,就是避免前者嵌套所产生布局树的高度,从而提高UI渲染的效率。
4-避免嵌套过多无用布局
1. 使用标签重用layout
将类似的内容来定义一个通用UI
* 将height width
设置为0dp
,迫使开发者对宽高进行重新设置(否则看不见)
<include layout="@layout/common_ui"
........
/>
注意:若需要覆盖原来原来布局的类似layout_xxxx
的属性
需要在include
中同时指定layout_width
和layout_height
属性
2. 使用实现View的延迟加载
- 轻量级组件:不可视、大小为0
< ViewStub >引用的布局没有显示出来
<ViewStub
android:id="@+id/not_often_use"
......
android:layout="@layout/not_often_use"/>
获得ViewStub组件
mViewStub = (ViewStub)findViewById(R.id.not_often_use); //viewstub的ID
显示该View的两种方式
mViewStub.setVisibility(View.VISIBLE)
- 2.
View flateView = mViewStub.inflate();
TextView textview = (TextView)inflateView.findViewById(R.id.tv);
- 不管是哪种方式,
ViewStub
就不存在了,取而代之的是被inflate
的Layout
,并将ID重新设置为ViewStub中android:inflateid属性所指的ID,因此两次调用inflate方法会报错
和View.Gone的区别?
ViewStub只会在显示的时候采取渲染布局
View.Gone 初始化布局树的时候已经添加在布局树上了
因此ViewStub更有效率
5-Hierarchy Viewer
现在在 android device monitor中可以使用
二、内存优化
android沙箱机制
,每个应用给定内存。过多内存会触发LMK
-Low Memory Killer
内存就是RAM
1-RAM组成:
Register:
stack:
存放基本数据类型
和对象的引用
但对象本身不存在stack,而是存放在堆
中- heap:
存放new创建的对象和数据。由GC
-Java虚拟机的垃圾回收器 - static field:
固定的位置存放应用程序运行时一直存在的数据,java中管理一些静态的数据变量 - constant pool:
java虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的有序集合,包括直接常量(基本类型,String)和对其他类型、字段、方法的符号引用。
stack和heap的区别
stack分配的内存空间会在该变量作用域结束后,这部分内存立即释放。
heap为new
创建的变量分配的空间,不会立即释放,而是等待系统GC
进行回收。
- 获得堆的大小
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
int heapsize= manager.getLargeMemoryClass();
2-内存回收
java创建垃圾收集器线程(Garbage Collection Thread)
进行资源管理。
调用
System.gc
能建议系统进行GC,但是不一定GC。
- 内存泄漏的原因:再强大的算法也会出现部分对象忘记回收的现象。
1.bitmap优化
bitmap
是内存占用过高,甚至OOM(out of memory)
的最大威胁。
- 使用分辨率适当的图片—
可以在图片列表使用图片的缩略图thumbnails
,显示图片的时候再显示原图。 - 使用图片缓存—通过内存缓存
LruCache
和硬盘缓存DiskLruCache
2.代码优化
- 对常量使用static修饰符
- 使用静态方法,静态方法会比普通方法提高15%的访问速度
- 减少不必要的成员变量,这点在Android Lint工具上已经集成检测了,如果一个变量可以定义为局部变量,则会建议你不要定义成成员变量。
- 减少不必要的对象,使用基础类型会比使用对象更加节省资源,同时更应该避免频繁创建短作用域的变量。
- 尽量不要用枚举、少用迭代器。
- 对Cursor、Receiver、Sensor、File等对象,要非常注意对它们的创建、回收与注册、解注册
- 避免使用IOC框架,IOC通常使用注解、反射来实现,虽然Java已经进行了很好的优化,但大量使用反射依然会带来性能的下降。
- 使用RenderScript、OpenGL进行复杂的绘图操作。
- 使用SurfaceView代替View进行大量、频繁的绘图操作。
- 尽量使用视图缓存,而不是每次都执行inflate()方法解析视图。
3-android的性能分析和优化工具
关于android的性能分析和优化工具,主要包括:Lint、Memory Monitor、TraceView、MAT、Dumpsys
1-Lint
Google提供的代码提示工具。用于减少代码隐藏风险,对代码习惯帮助很大。而且还能清除无用的文件等内容。
Analyze->Run inspection by name > unused resources=去除无用资源
1-contentDescription
问题:
在开发android时,在定义一个ImageVIew控件时,总是提示这个警告:[Accessibility] Missing contentDescription attribute on image属性解释:
这个属性必须在用户的Accessible 中的相应属性开启后才能使用。用户点击这个控件。android系统会自动使用人声朗读控件上android:contentDescription属性说指向的内容。这样用户就可以知道这个控件是做什么用的。这个属性的主要功能就是为视力有障碍的人增加对控件的解释。解决:
android:contentDescription=”@null”
2-textsize
用sp会因为用户字体设置的大小而改变,dp不会。
4.不要在draw代码中进行内存分配
2-Memory Monitor
内存监视工具:
内存持续升高可能发生内存泄露
内存突然降低,可能GC
3-TraceView日志
可以分析一些性能问题,比如app中有些列表在滑动的时候会有卡顿现象。
1-代码精确生成traceview日志
- 在manifest中增加WRITE_EXTERNAL权限
- 在需要监控的代码onCreate和onDestory中添加代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qqside_menu);
//开启TraceView监听
Debug.startMethodTracing("feather"); //制定名字如feather.trace
}
protected void onDestroy() {
super.onDestroy();
//结束监听
Debug.stopMethodTracing();
}
3.复制日志代码到本地
adb pull /sdcard/feather.trace C:\AFeatherTool
adb是在sdk的platform-tools中的工具。这里文件名是feather.trace,复制到了本地C:\AFeatherTool
目录下。
2-通过Android Device Monitor生成TraceView日志
打开AS的Android DEVICE Monitor工具,选择调试的进程,点击工具栏中的“start method profiling”。
有两种监听方式:
1. 整体监听:追踪每个方法执行的全部过程,资源消耗大
2. 抽样监听:按照一定频率采样,这种方法需要执行较长的时间来获取准确的数据。
3-打开traceview日志
sdk的tools\traceview.bat工具来打开。或者ADM openfile来打开日志文件。
4-分析日志
上方是用于显示方法执行时间的时间轴区域。下方是显示详细信息的profile区域。
时间轴区域:显示了不同线程在不同时间段内的执行情况。每一行都是一个独立线程。
profile:所选方法执行期间的性能分析。Incl CPU time-占用CPU的时间。Excl CPU TIME-方法本身不包括子方法的占用CPU的时间。Incl/Excl real time-同理,是真正执行的时间。calls+RecurCalls-掉用次数+递归回调的次数。
占用时间长,calls+RecurCalls次数少的需要多关注。
4-MAT分析APP内存状态
MAT(Memory analyzer tool)是分析内存的强力助手。需要下载。
1-生成HPROF文件
- 打开ADM
- 选择要监听的线程
- 菜单栏”update heap”
- heap的标签中选择Cause GC就会显示当前内存状态。
- 选择“Dump HPROF File”按钮,会生成xxx.hprof文件。
- 在SDK的platform-tools中用
hprof-conv C:\xxxx.hprof heap.hprof
之后才可以用来分析 - MAT打开即可分析
内存泄露技巧:
不停点击cause GC,如果total size有明显变化就可能存在内存泄露。
…MAT功能强大,以后再实际研究。
5-使用Dumpsys命令分析系统状态
Dumpsys可以列出android系统相关的信息和服务状态。
adb shell dumpsys + 各种参数
就可以使用。
Linux下配合shell命令grep、find等功能更加强大
6-其他工具
1、开发者-Profile GPU Rendering-on screen as bars-检测UI渲染时间,保证都在绿色线之下
2、开发者-Enable GPU Overdraw-通过界面颜色判断overdraw的次数。尽量加大蓝色,减少红色。
3、Hierarchy Viewer
4、Memory Info-系统上的内存监视工具
5、暂无