Android性能优化

总结归纳自《Android开发艺术探索》、《Android群英传》等关于性能优化资料。
转载请注明链接:http://blog.csdn.net/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呈现模式分析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

猎羽

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

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

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

打赏作者

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

抵扣说明:

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

余额充值