1、性能优化分析工具学习
· System Trace
Systrace是一个收集和检测时间信息的工具,它能显示CPU和时间被消耗在哪儿了,每个进程和线程都在其CPU时间片内做了什么事儿.而且会指示哪个地方出了问题,以及给出Fix建议。给出的结果trace文件是以html形式打开的,直接用浏览器打开查看十分方便。打开方法:打开DDMS后,连接手机,点击手机上方一排按钮中的SysTrace按钮。打开的效果如下图:
· Hierarchy Viewer
Hierarchy Viewer提供了一个可视化的界面来观测布局的层级,让我们可以优化布局层级
· TraceView
2、布局优化
Android中布局优化主要包含以下三个方面:布局层级和测量次数、布局过度绘制、绘制过程
1、布局层级与测量次数
(一)合理选择父容器
FrameLayout、不带Layou_wight的LinearLayuut、RelativeLayout。因为带有Layot_weight的LinearLayout和RelativeLayout会测量两次。
Android studio3.0开始,Google不建议使用它, 因此我们需要手动在sdk目录下的tools中找到它,之后运行你的apk并且选择Hierarchy View,就可以查看对应的层级关系,如下:
include标签的作用就是可以直接引用已有的布局,而不需要重新写布局。而通常会将include和merge标签相结合使用,下面会介绍merge标签。
merge标签通常是作为include标签的辅助扩展,就是为了解决引入include后导致布局层级增加问题,使用merge标签后,引入的布局中的View就会作为父布局的子View。如下:
ViewStub继承于View,它是一个轻量级且宽高为0的组件,本身不参与布局和绘制。因此使用它可以做到在不需要的时候不加载,在需要的时候再加载,从而提高性能。那么如何做到需要的时候显示呢?
setVisiable
Constaint Layout允许在不使用任何嵌套的情况下创建复杂布局,与Relative Layout
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@+id/iv_image"
2、过度绘制
· Android device monotor
避免在onDraw()方法中分配对象,因为onDraw方法可能被多次调用,这样的话可能会产生很多不必要的对象使用ClipRect制定个绘制区域在使用自定义View时,我们可以利用此方法来指定一块可见区域,用于绘制,其他区域则会被忽略,即只绘制clipRect指定的区域。例如在图片层叠时,我们将重叠部分不再绘制,只绘制不重叠部分。直接绘制如下:
3、线程优化
1.不能通过非UI线程对View进行操作。因为Android的UI不是安全的,如果View能被不同的线程所访问或修改,那么就可能在程序的执行期间,产生不可预期的行为或者并发错误。
2.使用线程时,避免在循坏中使用同步,因为获取和释放锁的操作代价很大。会引起CPU资源的损耗。
3.处理多线程以及线程间通信时,使用HandlerThread来操作,它内部包装了Looper,记得不用的时候退出/释放资源哦。
4.当工作线程与UI线程之间通信的时候,推荐使用AsyncTask(Android 7.0后内部任务变成串行处理,不再会出现以前并行时超过任务数执行饱和策略的情况)
5. Loader可以用来代替AsyncTask的某些情况,因为Loader的生命周期是独立的(与Application Context有关),当Activity/Fragment销毁重建时,它仍然在,而且它特别使用异步操作,比如AsyncTaskLoader代替AsyncTask也可以实现后者的功能,但是生命周期完全独立于Activity。切记Loader使用完记得销毁。
6.当你的Service不需要交互时,请使用可以自动停止的IntentService。
7.当你希望延长BroadcastReceiver的生命周期时,例如启动一个后台线程IntentService。在onReceiver中调用BroadcastReceiver.goAsync(),它会返回一个PendingResult对象,这时,广播接收器的生命周期会延长持续到PendingResult.finish()方法调用。
8.线程池最好用构造方法手动创建,而不要用Executors来直接调用工厂方法,这样利于明白线程池的运行规则,避免用了错误的线程池导致资源耗尽。
9.给线程一个好听的名字,调试时候用。
10.线程池设置线程的存活时间,以保证空闲线程准确释放。
4、内存泄漏
5、算法优化
6.其他优化点
在Activity、Fragemnt的onCreate等初始化方法中,如果执行了太耗时的操作(例如读取各种数据),会影响页面的加载速度,让用户觉得APP太慢。这时候可以异步处理这些耗时任务,减小应用启动的时候的负担。
尽管矢量图有诸多优点,但矢量图的绘制是消耗性能的。在应用初始化加载等比较影响用户体验的地方,还是建议使用Bitmap来代替矢量图,提高APP开启效率。
经小伙伴用TraceView不断的打点发现,正则表达式非常消耗时间。因此尽管正则表达式非常优雅,涉及到性能问题的时候,可以改为其他判断方式来提高APP性能。
在Java中浮点类型的运算大概比整型数据慢两倍,因此整型数据能解决的问题尽量用整型。
log 开发的时候用于调试的log,在项目上线的时候没用的要及时删除。当然有用的log还是要留下,以便以后分析问题。
没用用的资源会增大APK大小,既然没有用了,上线的时候当然要及时删除。
Lint代码检查 使用Lint等静态代码检查工具可以帮助我们发现很多隐藏的问题。Lint检查出来的问题越少,说明代码越规范,越不容易出现各种问题,APP性能自然也会提升。
全局广播也是十分消耗性能的一个点。对于应用内的通讯,使用接口回调,EventBus等手段比起广播是更好地选择。动态注册广播的时候,也不要忘了广播的注销。