Android性能优化

总结归纳自《Android开发艺术探索》、《Android群英传》等关于性能优化资料。
转载请注明链接:http://blog.youkuaiyun.com/feather_wch/article/details/79615455

Android性能优化

版本: 2018/3/20-1

1、UI渲染机制

  1. 系统通过VSYNC信号触发对UI的渲染、重绘,其间隔时间是16ms。
  2. 这个16ms其实就是1000ms显示60帧画面的单位时间
  3. 如果不能在16ms内完成绘制,那么就会造成丢帧现象。会在下个信号才开始绘制(2*16ms)—导致卡顿

布局优化

2、布局优化的思想

  1. 减少布局文件层级
  2. 使用高性能布局

3、View是什么?

  1. View是Android系统在屏幕上的视觉呈现.
  2. View是一种控件

4、View是怎么绘制出来的?

  1. View的绘制流程是从ViewRoot的performTraversals()方法开始
  2. measure()
  3. layout()
  4. draw()

5、View是怎么呈现在界面上的?

  1. Android中的视图都是通过Window来呈现的(Activity、Dialog还是Toast都有一个Window)
  2. 然后通过WindowManager来管理View。
  3. Window和顶级View——DecorView的通信是依赖ViewRoot完成的。

6、View和ViewGroup什么区别?

  1. View是所有控件和布局的父类。
  2. ViewGroup也属于View,构成一种树状结构

7、视图优化的几种方法

  1. 减少画面绘制的时间
  2. 避免过度绘制
  3. 优化布局层级
  4. 避免嵌套过多无用布局

8、RelativeLayout和LinearLayout的性能差异

  1. 两者layout和draw性能相等,区别在于measure过程
  2. RelativeLayout对所有子View会进行两次measure(横向+纵向)—因为子View间可能同时有纵向和横向的依赖关系,所有都需要进行一次测量。
  3. LinearLayout会进行一次measure,如果有weight属性才会进行第二次measure

9、布局的选择

  1. 如果不涉及到层级深度,应该选择高效的LinearLayout或者FrameLayout
  2. 涉及到层级深度时,如ListView中更适合使用RelativeLayout,且尽可能使用pading代替margin
  3. ConstraintLayout是性能最好的布局!

10、布局层级优化的三种方法

  1. include标签
  2. merge标签
  3. ViewStub

11、include标签的特点和使用方法

  1. include主要是用于布局重用,就不需要重复写相同的布局
  2. include中只支持layout_开头的属性,如果指定了id则会覆盖掉所包含的布局文件根元素的id属性
//main.xml
<android.support.constraint.ConstraintLayout ...>
    <include
        android:id="@+id/include"
        layout="@layout/my_include_layout"
        android:layout_width="200dp"
        android:layout_height="200dp"
        .../>
    <TextView
        android:id="@+id/sample_text"
        ... />
</android.support.constraint.ConstraintLayout>

//my_include_layout.xml
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/sample_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        .../>

</android.support.constraint.ConstraintLayout>

12、merge标签的作用

  1. merge一般配合include标签使用,用于减少布局层级
  2. 假如include标签外层是LinearLayout,内部布局根元素的布局也是LinearLayout ,使用merge能减少不必要的层级。
//需要将include所包含的内部布局的根布局使用merge标签,如my_include_layout.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <TextView
        android:id="@+id/sample_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="I'm include"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</merge>

13、ViewStub的作用和使用

  1. 轻量级组件(继承View):不可视、大小为0
  2. ViewStub一旦进行显示,就不存在了,取而代之的是被inflate的布局,并将ID设置为ViewStub中android:inflateid属性所指的ID,因此两次调用inflate方法会报错
  3. ViewStub还不支持merge标签
<ViewStub
 android:id="@+id/not_often_use"
 ......
 android:layout="@layout/not_often_use"/>
//1. 获得ViewStub组件
mViewStub = (ViewStub)findViewById(R.id.not_often_use); //viewstub的ID
//2-1. 显示该View的第一种方法
mViewStub.setVisibility(View.VISIBLE)
//2-2. 显示该View的第二种方法
View flateView = mViewStub.inflate();
TextView textview = (TextView)inflateView.findViewById(R.id.tv);

14、绘制优化-优化View的onDraw方法

  1. onDraw中不要创建新的局部对象onDraw可能会频繁调用,瞬间创建大量对象和大量GC
  2. onDraw中不要做耗时的任务,尽量要保证View的绘制频率60fps(每帧画面不超过16ms)

内存优化

15、内存泄漏优化

  1. 静态变量所导致的内存泄漏:如Activity内部静态变量持有Activity的this等
  2. 单例模式导致的内存泄漏:单例模式的对象中的链表等持有了如:Activity的this指针,却没有即使释放会导致泄露,因为单例的特点是其生命周期和Applicaiton一致。
  3. 属性动画不停止会导致内存泄漏:无限循环动画会持有Activity的View,而View持有了Activity,最终导致泄露。解决办法是在onDestory中调用animator.cancel()

16、ANR是什么?

  1. UI线程执行耗时操作会导致ANR
  2. 如果BroadcastReceiver10秒没有执行完操作,就会导致ANR

17、ANR如何分析?

  1. 只要出现ANR,系统都会在/data/anr/目录下生成相应的trace.txt
  2. 根据内容可以分析ANR的具体原因

18、ANR出现的几种特殊情况

  1. 主线程UI线程中进行耗时操作
  2. UI线程和在其他线程的耗时操作竞争同一个锁。

19、ListView/GridView的优化

  1. 采用ViewHolder
  2. 避免在getView中执行耗时操作
  3. 根据滑动状态控制任务的执行频率,避免快速滑动时开启大量的异步操作。
  4. 开启硬件加速,使列表滑动更流畅。

20、Bitmap的优化

  1. 选择合适大小图片, 也可以在图片列表时显示缩略图,显示图片的时候使用原图
  2. 通过BitmapFactory.Options对图片进行采样、
  3. 图片缓存-使用内存缓存LruCache硬盘缓存DiskLruCache

21、线程优化

  1. 采用线程池,避免线程的创建和销毁带来的性能损失
  2. 线程池能有效控制最大并发数,避免抢占资源导致的阻塞

22、性能优化建议

  1. 避免创建过多的对象
  2. 不要过多使用枚举,枚举所占空间比整数大。少用迭代器。
  3. 常量使用static final进行修饰
  4. 使用Andorid特有的数据类型,如SparseArray和Pair,性能更好。
  5. 适当使用软引用弱引用
  6. 采用内存缓存和硬盘缓存
  7. 尽量使用静态内部类,避免由于内部类导致的内存泄露
  8. 使用静态方法,静态方法会比普通方法提高15%的访问速度
  9. 减少不必要的成员变量,这点在Android Lint工具上已经集成检测了,如果一个变量可以定义为局部变量,则会建议你不要定义成成员变量。
  10. 减少不必要的对象,使用基础类型会比使用对象更加节省资源,同时更应该避免频繁创建短作用域的变量。
  11. 对Cursor、Receiver、Sensor、File等对象,要非常注意对它们的创建、回收与注册、解注册
  12. 避免使用IOC框架,IOC通常使用注解、反射来实现,虽然Java已经进行了很好的优化,但大量使用反射依然会带来性能的下降。
  13. 使用RenderScript、OpenGL进行复杂的绘图操作。
  14. 使用SurfaceView代替View进行大量、频繁的绘图操作。
  15. 尽量使用视图缓存,而不是每次都执行inflate()方法解析视图。

22、性能优化工具汇总

  1. UI渲染时间工具:开发者中选择Profile GPU Rendering(GPU呈现模式分析),选择On Screen as bars能开启条形图。蓝色线条为绘制的时间,要控制在绿线之下。
  2. 过度绘制:开发者中Enable GPU OverDraw(开启过度绘制检查)
  3. 布局层级:Hierarchy Viewer,在Android Device Monitor中使用。
  4. 代码提示工具:Lint
  5. Memory Monitor
  6. TraceView日志
  7. MAT
  8. Dumpsys
  9. Memory Info

参考资料

  1. Android性能优化《Android群英传》第十章
  2. RelativeLayout和LinearLayout的性能对比
  3. 【腾讯优测干货分享】安卓专项测试之GPU测试探索
  4. Android开发者选项——Gpu呈现模式分析
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猎羽

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

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

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

打赏作者

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

抵扣说明:

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

余额充值