Android 性能优化-《Android群英传》第十章

一、布局优化

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_widthlayout_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的两种方式
  1. mViewStub.setVisibility(View.VISIBLE)
  2. 2.
View flateView = mViewStub.inflate();
TextView textview = (TextView)inflateView.findViewById(R.id.tv); 
  • 不管是哪种方式,ViewStub就不存在了,取而代之的是被inflateLayout,并将ID重新设置为ViewStub中android:inflateid属性所指的ID,因此两次调用inflate方法会报错
和View.Gone的区别?

ViewStub只会在显示的时候采取渲染布局
View.Gone 初始化布局树的时候已经添加在布局树上了

因此ViewStub更有效率

ViewStub

5-Hierarchy Viewer

现在在 android device monitor中可以使用

二、内存优化

android沙箱机制,每个应用给定内存。过多内存会触发LMK-Low Memory Killer
内存就是RAM

1-RAM组成:

  1. Register:

  2. stack:
    存放基本数据类型对象的引用
    但对象本身不存在stack,而是存放在

  3. heap:
    存放new创建的对象和数据。由GC-Java虚拟机的垃圾回收器
  4. static field:
    固定的位置存放应用程序运行时一直存在的数据,java中管理一些静态的数据变量
  5. 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)的最大威胁。

  1. 使用分辨率适当的图片—
    可以在图片列表使用图片的缩略图thumbnails,显示图片的时候再显示原图。
  2. 使用图片缓存—通过内存缓存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
  1. 问题:
    在开发android时,在定义一个ImageVIew控件时,总是提示这个警告:[Accessibility] Missing contentDescription attribute on image

  2. 属性解释:
    这个属性必须在用户的Accessible 中的相应属性开启后才能使用。用户点击这个控件。android系统会自动使用人声朗读控件上android:contentDescription属性说指向的内容。这样用户就可以知道这个控件是做什么用的。这个属性的主要功能就是为视力有障碍的人增加对控件的解释。

  3. 解决:
    android:contentDescription=”@null”

2-textsize

用sp会因为用户字体设置的大小而改变,dp不会。

4.不要在draw代码中进行内存分配

2-Memory Monitor

内存监视工具:
内存持续升高可能发生内存泄露
内存突然降低,可能GC

3-TraceView日志

可以分析一些性能问题,比如app中有些列表在滑动的时候会有卡顿现象。

1-代码精确生成traceview日志
  1. 在manifest中增加WRITE_EXTERNAL权限
  2. 在需要监控的代码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文件
  1. 打开ADM
  2. 选择要监听的线程
  3. 菜单栏”update heap”
  4. heap的标签中选择Cause GC就会显示当前内存状态。
  5. 选择“Dump HPROF File”按钮,会生成xxx.hprof文件。
  6. 在SDK的platform-tools中用hprof-conv C:\xxxx.hprof heap.hprof之后才可以用来分析
  7. 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、暂无

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值