第十章:Android 性能优化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38515203/article/details/82885027

《Android群英传》——个人读书笔记

10.1 布局优化

10.1.1 Android UI 渲染机制

        Android系统通过 VSYNC信号 触发对UI的渲染、重绘。其时间间隔在16ms(1000ms显示60帧画面的单位时间)以内。超过16ms就会造成 丢帧现象 ,即当前该重绘的帧被未完成的逻辑阻塞。
        可通过开发者选项打开检测UI渲染时间的工具。每一条柱状图包含三个部分:

  • 蓝色:测量绘制Display List的时间
  • 红色:OpenGL 渲染Display List所需的时间
  • 黄色:CPU等待GPU处理的时间

中间的绿色横线代表VSYNC时间(16ms),需要尽量将所有条形图都控制在这条绿线之下。

10.1.2 避免 Overdraw

  • Overdraw——过度绘制,过度绘制会浪费很多的CPU、GPU资源。

10.1.3 优化布局层级

  • 系统对View的测量、布局以及绘制时,都是通过遍历View树来进行操作的。

因此优化布局的第一个方法就是 降低View树的高度 Google API 建议不超过10层。

10.1.4 避免嵌套过多无用布局

10.1.4.1 使用<include>标签重用Layout

  •  

10.1.4.2 使用<ViewStub>实现View的延迟加载

  • 一个轻量级的组件,不仅不可见,且大小为0
  • 引用方式与 include 相同,但此时引用的布局并没有显示出来,显示的方式有两种:
    1)VISIBLE
         mViewStub.setVisiblility(View.VISIBLE);
    2)inflate
         View inflateView = mViewStub.inflate();

一旦<ViewStub>被设置为可见或是被inflate,<ViewStub>就不存在了,取而代之的被inflate的Layout。并将这个Layout的ID重新设置为<ViewStub>中通过 android:infaltedId 属性所指定的ID,这也是为什么两次调用inflate方法会报错的原因。

  • <ViewStub>标签 与设置 View.GONE 的区别

共同点都是在初始时不会显示布局,但是 标签 只会在显示时,才去渲染这个布局,而View.GONE在初始化布局树的时候就已经添加在布局树上了。所以相比之下,标签的效率更高。

10.1.5 Hierarchy Viewer

Hierarchy Viewer 无法在加密过的真机设备上使用。

  • Google大神 Runmain Guy 提供了一个开源项目 View Server 可以在真机上使用 Hierarchy Viewer github地址

10.2 内存优化

10.2.1 什么是内存

        由于Android应用的沙箱机制,每个应用分配的内存大小是有限制的,内存太小则会触发 LMK——Low MeMary Killer机制

  • 内存 通常情况下就是我们所说的手机的 RAM
        包含五个部分:
  • 1)寄存器(Registers)——速度最快的存储场所(因为寄存器位于处理器内部,在程序中无法控制)。
  • 2)栈(Stack)——存放基本类型的数据以及对象的引用,但对象本身并不存放在栈中,而是存放在堆中。
  • 3)堆(Heap)——存放由 new 创建的对象和数组。在堆中分配的内存,由java虚拟机的自动回收器(GC)来管理。
  • 4)静态存储区域(Stack Field)——指在固定的位置存放应用程序运行时一直存在的数据,java在内存中专门划分了一开静态存储区域来管理一些特殊的数据变量,如静态的数据变量。
  • 5)常量池(Constant Pool)——JVM虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到的常量的一个有序的集合,包含直接常量(基本类型,String)和对其他类型、字段和方法的符号引用。
            当定义一个变量,Java虚拟机就会在栈中为该变量分配内存空间,当该变量作用域结束后,这部分内存空间会马上被用作新的控件进行分配。如果使用new的方式创建一个变量,那么就会在堆中为这个对象分配内存空间,即使该对象的作用域结束,这部分内存也不会立即被回收,而是等待系统GC进行回收。

所谓的内存分析,就是分析Heap中的内存状态。

10.2.2 获取Android系统内存信息

10.2.2.1 Process Stats

  • 系统内存监视服务

10.2.2.2 Meminfo

  • 内存监视工具

10.2.3 内存回收

  • Java创建了垃圾收集器线程(Garbage Collection Thread)来自动的进行资源管理。从而降低了开发人员对内存管理的繁杂工作。

10.2.4 内存优化实例

10.2.4.1 Bitmap实例

  • Bitmap是造成内存占用过高甚至OOM的最大威胁。
  • 使用Bitmap的小技巧:
    1)使用适当分辨率和大小的图片
    2)及时回收内存 —— Android3.0之前,使用完需调用 bitmap.recycle() 方法进行内存的释放。3.0之后,Bitmap被放到了 堆 中,其内存由 GC 管理,不需要再手动进行释放。
    3)使用图片缓存 —— 通过 内存缓存(LruCache)硬盘缓存(DiskLruCache) 可以更好的使用Bitmap

10.2.4.2 代码优化

  • 从代码的实现方式上,进行优化:
    1)对常量使用 static 修饰符
    2)使用静态方法(静态方法比普通方法提高约15%的访问速度)
    3)减少不必要的成员变量
    4)减少不必要的对象。使用基础类型回避使用对象更加节省资源
    5)尽量不要使用枚举、少用迭代器
    6)对Cursor、Receiver、Sensor、File等,要非常注意对他们的创建、回收与注册、解注册。
    7)避免使用IOC框架。IOC 通常使用注解、反射来进行实现,Java已对反射的效率做了很好的优化,但是大量的使用反射依旧会造成性能的下降。
    8)使用RenderScript、OpenGl 来进行非常复杂的绘图操作
    9)使用SurfaceView 来替代 View 进行大量、频繁的绘图操作
    10)尽量使用视图缓存,而不是每次都执行inflate()方法解析视图

10.3 Lint 工具

  • 它是AS中集成的一个Android代码提示工具

10.4 使用 Android Studio 的 Memory Monitor 工具

  • AS自带的一个内存监视工具,可以帮助我们进行内存的分析。

10.5 使用 TraceView 工具优化 APP 性能

  • Android下可视化性能调查工具

10.5.1 生成 TraceView 日志的两种方法

        一种是利用Debug类帮助我们生成日志文件,另一种是利用 Android Device Monitor 工具辅助生成日志文件。

10.5.1.1 通过代码生成精确范围的 TraceView 日志

  • 开启监听:Debug.startMethodTracing()
  • 关闭监听:Debug.stopMethodTracing()

TraceView 的日志会保存在 “/sdcard/dmtrace.trace” 目录下,所以需要在Mainifest文件中添加如下权限:

<uses-permission
android:name="anroid.permission.WRITE_EXTERNAL_STORACE">
  • 当被监听的内容执行完毕之后,通过ADB命令到导出本地:
    adb pull/sdcard/trace_log.trace/local/LOG/

10.5.1.2 通过 Android Device Monitor 生成 TraceView 日志

    TraceView 提供了两种监听方式:

  • 整体监听
    跟踪每个方法执行的全部过程,但资源消耗很大
  • 抽样监听
    按照指定的频率抽样调查。执行时间长,获取样本数据准确。

10.5.2 打开 TraceView 日志

        对于导出的 TraceView 日志文件,可以使用SDK中的 “sdk\tools\traceview.bat” 工具来打开。或者使用ADM工具打开。

10.5.3 分析 TraceView 日志

10.5.3.1 时间轴区域

        显示不同线程在不同时间段内的执行情况,其中的 每一行 都代表了一个独立的线程。不同的色块 代表不同的执行方法,色块的长度 代表方法所执行的时间。

10.5.3.1 Profile 区域

        区域内显示,你选择的色块所代表的方法在该色块所处的时间段内的性能分析。

  • Incl CPU Time 某方法占用CPU的时间
  • Excl CPU Time 某方法本身(不包括子方法)占用CPU的时间
  • Incl Real Time 某方法真正执行的时间
  • Excl Real Time 某方法本身(不包括子方法)真正执行的时间
  • Calls+RecurCalls 调用次数+递归回调的次数

每个时间都包含两列,一个是实际的时间,另一个是百分比。分析的时候通常从 Incl CPU TimeCalls+RecurCalls 开始进行分析,对占用时间长的方法中点分析,如果占用时间长,并且 Calls+RecurCalls 次数又少,那么就可以列为怀疑对象了。

10.6 使用MAT工具分析App内存状态

  • MAT——Memory Analyzer Tool

10.6.1 生成 HPROF 文件

  •  

10.6.2 分析 HPROF 文件

  •  

10.7 使用 Dumpsys 命令分析系统状态

  • 使用 Dumpsys 命令可以列出 Android 系统相关的信息和服务状态
  • 使用 adb shell dumpsys + 指定参数 就可以获得相应的信息,例如获取 activity 栈的详细信息:adb shell dumpsys activity
  • 常用的 Dumpsys 参数:
参数 含义
activity 显示所有的Activity栈的信息
meminfo 内存信息
battery 电池信息
package 包信息
wifi 显示Wi-Fi信息
alarm 显示alarm信息
procstats 显示内存状态

猜你喜欢

转载自blog.csdn.net/weixin_38515203/article/details/82885027