Android进阶之路 - 性能优化的自我总结

性能优化:
在我认为聪明的人,从开始就已经在做优化,而像我们大多数人的话,只有在项目完成之后,重构之处才会用到 > <~

概念

  • 百度百科:
    性能优化,简而言之,就是在不影响系统运行正确性的前提下,使之运行地更快,完成特定功能所需的时间更短

作用

  • 移动端:
    提升用户体验,减少卡顿,不流畅,经常崩溃等现象

  • 前端
    提升用户体验,减少卡顿,不流畅等现象

  • 后端
    方便代码后期重构,提升代码执行效率

优化方向

  • 布局优化
  • 绘制优化
  • 线程优化
  • 响应速度优化
  • 内存优化
  • 其他优化方式

性能优化与其他优化方式是一种包含的关系,其中有内存优化,同时也包含所有其他的优化方式,进阶吧,皮卡丘 ~

布局优化

  • 布局嵌套太深

有的时候为了赶进度,布局设计不是很好,往往嵌套层次太深,随随便便Layout就几百号代码,显的很臃肿

建议:LinearLayout层次嵌套太多的时候,查看是否可以采用RelativeLayout进行优化

  • 标签复用(合理使用 include、merge 标签)

在布局文件中,include标签可以指定插入一段布局文件到当前布局。这样的话既提高了布局复用,也减少了我们的代码书写。另外,merge标签可以和include的标签一起使用从而减少布局层级。

建议:当某一块布局,被多个布局同时用到,外层的LinearLayout、RelativeLayout可以采用merge标签复用,如果是内层的服用的话,可以用到include标签

  • ViewStub延时加载

有些布局,比如网络出错或空界面的布局,没必要在所有时候都加载出来,我们可以在用户特定的时间触发

建议:使用ViewStub可以实现按需加载。ViewStub本身没有宽高,加载起来几乎不消耗什么资源

Android布局优化之include、merge、ViewStub的使用

  • 视图的显示问题(不是很确定优化结果)

布局中没展示前Gone的状态,触发的时候 setVisibility(View.VISIBLE)会调用它引用的真实布局填充到当前位置,从而实现了延时加载,节省了正常加载的时间

绘制优化 :

  • 过度绘制(概念)

描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的 UI 结构里面,如果不可见的 UI 也在做绘制的操作,会导致某些像素区域被绘制了多次,同时也会浪费大量的 CPU 以及 GPU 资源

绘制优化是指View的onDraw方法要避免执行大量的操作,俩方面讲明

  • onDraw中不要创建新的局部对象(减少频繁调用)

因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁gc,降低了程序的执行效率。

  • onDraw方法中不要做耗时的任务,也不能执行成千上万次的循环操作,尽管每次循环都很轻量级,但是大量的循环仍然十分抢占CPU的时间片,这会造成View的绘制过程不流畅

按照Google官方给出的性能优化典范中的标准,View的绘制频率保证60fps是最佳的,这就要求每帧绘制时间不超过16ms(16ms = 1000/60),虽然程序很难保证16ms这个时间,但是尽量降低onDraw方法中的复杂度总是切实有效的

线程优化 :

线程的创建和销毁会带来比较大的性能开销。因此线程优化也很有必要。查看项目中是否存在随意new thread,线程缺乏管理的情况。使用AsyncTask或者线程池对线程进行管理,可以提升APP的性能。

  • Java多线程之锁优化策略
  • 聊聊并发(三)Java线程池的分析和使用

响应速度优化 (ANR):

  • ANR(Application Not responding)

Android中,主线程(UI线程)如果在规定时内没有处理完相应工作,就会出现ANR;换言之,耗时操作放在了主线程执行,导致限定时间内程序无响应

解决方案 :
耗时操作放在子线程执行,执行完毕之后通过Handler传回主线程进行是哟ing

ANR对应的响应时间 :

  • 输入事件(按键和触摸事件)5s内没被处理: Input event dispatching timed out
  • BroadcastReceiver的事件(onRecieve方法)在规定时间内没处理完(前台广播为10s,后台广播为60s):Timeout of broadcast BroadcastRecord
    07-27 19:18:47.448 1707 1766 W BroadcastQueue: Receiver during timeout: ResolveInfo{ccd831e com.example.qintong.myapplication/.MyBroadCastReciever m=0x108000}
    07-27 19:18:47.502 3513 3728 I WtEventController: ANR com.example.qintong.myapplication 7573
  • service 前台20s后台200s未完成启动 Timeout executing service
  • ContentProvider的publish在10s内没进行完:timeout publishing content providers
    在android文档(https://developer.android.com/training/articles/perf-anr.html)中,只写了第一种和第二种情况,而根据源码和实际的实验,我们能发现service的启动和provider的publish同样会造成anr问题。
    这里需要注意的是,在后三种情况,以BroadcastReviever为例,在onRecieve()方法执行10秒内没发生第一种ANR(也就是在这个过程中没有输入事件或输入事件还没到5s)才会发生Receiver timeout,否则将先发生事件无相应ANR,所以onRecieve()是有可能执行不到10s就发生ANR的,所以不要在onRecieve()方法里面干活,service的onCreate()和ContentProvider的onCreate()也一样,他们都是主线程的,不要在这些方法里干活,这个会在本文最后再细说。

  • Android ANR问题总结

内存优化 :

我会单独写一篇文章,用于记录内存优化的方案

其他优化 :

我会单独写一篇文章,用于记录其他优化的方案

借鉴文章 :

  • 关于Android性能优化,该从哪些方面入手?
  • Android开发性能优化总结(一)

你可能感兴趣的:(Android进阶之路)