Android性能优化

一,UI性能问题
UI卡顿原理:虚拟机在执行GC垃圾回收操作时所有线程(包括UI线程)都需要暂停,当GC垃圾回收完成之后所有线程才能够继续执行,所以页面必须在16ms内完成GC和渲染操作才能保证不丢帧卡顿问题。

UI卡顿原因:
1,在UI线程做了轻微的耗时操作。
2,布局layout过于复杂,无法在16ms内渲染完成。
3,同一时间动画执行的次数过多,导致CPU或GPU负载过重。
4,View过度绘制,导致某些像素在同一帧时间内被绘制多次,从而使CPU或GPU负载过重。
5,View频繁的触发measure、layout,导致measure、layout累计耗时过多及整个View频繁的重新渲染。
6,内存频繁触发GC过多(同一帧中频繁创建内存),导致暂时阻塞渲染操作.
7,冗余资源及逻辑等导致加载和执行缓慢.
8,臭名昭著的ANR.

UI卡顿解决的办法:
A。工具类解决
1,在设置->开发者选项->调试GPU过度绘制。
2,在设置->开发者选项->GPU呈现模式。
3,击右键->Analyze->Inspect Code–>界面选择你要检测的模块->点击确认开始检测(使用Lint进行资源及冗余UI布局等优化)。
4,使用traces.txt文件进行ANR分析优化。
B。代码避免
1,尽量避免在重复触发的逻辑代码中进行大量对象分配。
2,尽量避免在多次for循环中频繁分配对象。
3,避免在自定义view的onDraw()方法中进行复杂的操作和分配对象。例如:不要在onDraw()中实例话paint。
4,布局优化:尽量使用include、viewstub、megre标签;尽量不存在复杂和冗余的布局;尽量使用Gone代替Invisible;使用weight后尽量将width和heigh设置为0dp减少运算;Item存在非常复杂的嵌套时考虑使用自定义Item View来取代,减少measure与layout次数等。
5,列表和adapter优化;尽量复用getview方法中相关的view,不重复获取实例,列表在滑动过程中尽量不进行UI刷新等。
6,背景和图片等内存分配优化;尽量减少不必要的背景设置,图片尽量压缩处理显示,尽量避免频繁内存抖动等问题出现。
7,自定义View等绘图与布局优化;尽量避免在draw、measure、layout中做过于耗时及耗内存操作,尤其是draw方法中,尽量减少draw、measure、layout等执行次数。
8,对于并发下载等类似逻辑的实现尽量避免多次创建线程对象,而是交给线程池处理。
9,避免ANR,不要在UI线程中做耗时操作,遵守ANR规避守则,譬如多次数据库操作等。

二,内存泄漏
内存管理原理:运行的App在自己的虚拟机中内存管理基本就是遵循Java的内存管理机制了,系统在特定的情况下主动进行垃圾回收。但是要注意的一点就是在Android系统中执行垃圾回收(GC)操作时所有线程(包含UI线程)都必须暂停,等垃圾回收操作完成之后其他线程才能继续运行。

内存泄漏的原因:造成内存泄露的最核心原理就是一个对象持有了超过自己生命周期以外的对象强引用导致该对象无法被正常垃圾回收;

内存泄漏检测工具: leakcanary和MAT

避免内存泄漏的方法:
1,Context使用不当造成内存泄露;不要对一个Activity Context保持长生命周期的引用。尽量在一切可以使用应用ApplicationContext代替Context的地方进行替换。
2,非静态内部类的静态实例容易造成内存泄漏;即一个类中如果你不能够控制它其中内部类的生命周期(譬如Activity中的一些特殊Handler等),则尽量使用静态类和弱引用来处理(譬如ViewRoot的实现)。
3,警惕线程未终止造成的内存泄露;譬如在Activity中关联了一个生命周期超过Activity的Thread,在退出Activity时切记结束线程。
4,对象的注册与反注册没有成对出现造成的内存泄露;譬如注册广播接收器、注册观察者(典型的譬如数据库的监听)等。
5,创建与关闭没有成对出现造成的泄露;譬如Cursor资源必须手动关闭,WebView必须手动销毁,流等对象必须手动关闭等。
6,不要在执行频率很高的方法或者循环中创建对象,可以使用HashTable等创建一组对象容器从容器中取那些对象,而不用每次new与释放。
7,避免代码设计模式的错误造成内存泄露。

三,内存溢出
内存溢出原因:
1,应用代码存在内存泄露,长时间积累无法释放导致OOM。
2,应用的某些逻辑操作疯狂的消耗掉大量内存(譬如加载一张不经过处理的超大超高清图片等)导致超过阈值OOM。
可以发现,无论哪种类型,导致内存溢出(OutOfMemoryError)的核心原因就是应用的内存超过阈值了。

避免内存溢出:
1,时刻记得不要加载过大的Bitmap对象;譬如对于类似图片加载我们要通过BitmapFactory.Options设置图片的一些采样比率和复用等,具体做法点我参考官方文档,不过过我们一般都用fresco或Glide开源库进行加载。
2,优化界面交互过程中频繁的内存使用;譬如在列表等操作中只加载可见区域的Bitmap、滑动时不加载、停止滑动后再开始加载。
3,有些地方避免使用强引用,替换为弱引用等操作。
4,避免各种内存泄露的存在导致OOM。
5,对批量加载等操作进行缓存设计,譬如列表图片显示,Adapter的convertView缓存等。
6,尽可能的复用资源;譬如系统本身有很多字符串、颜色、图片、动画、样式以及简单布局等资源可供我们直接使用,我们自己也要尽量复用style等资源达到节约内存。
7,对于有缓存等存在的应用尽量实现onLowMemory()和onTrimMemory()方法。
8,尽量使用线程池替代多线程操作,这样可以节约内存及CPU占用率。
9,尽量管理好自己的Service、Thread等后台的生命周期,不要浪费内存占用。
10,尽可能的不要使用依赖注入,中看不中用。
11,尽量在做一些大内存分配等可疑内存操作时进行try catch操作,避免不必要的应用闪退。
12,尽量的优化自己的代码,减少冗余,进行编译打包等优化对齐处理,避免类加载时浪费内存。

四,Android应用API使用及代码逻辑性能分析
1,避免在Android中使用Java的枚举类型,因为编译后不但占空间,加载也费时,完全没有static final的变量好用、高效。
2,Handler发送消息时尽量使用obtain去获取已经存在的Message对象进行复用,而不是新new Message对象,这样可以减轻内存压力。
3,在使用后台Service时尽量将能够替换为IntentService的地方替换为此,这样可以减轻系统压力、省电、省内存、省CPU占用率。
4,在当前类内部尽量不要通过自己的getXXX、setXXX对自己内部成员进行操作,而是直接使用,这样可以提高代码执行效率。
5,不要一味的为了设计模式而过分的抽象代码,因为代码抽象系数与代码加载执行时间成正比。
6,尽量减少锁个数、减小锁范围,避免造成性能问题。
7, 合理的选择使用for循环与增强型for循环,譬如不要在ArrayList上使用增强型for循环等。

五,Android应用移动设备电池耗电性能分析
1,在需要网络的应用中,执行某些操作前尽量先进行网络状态判断。
2,在网络应用传输中使用高效率的数据格式和解析方法,譬如JSON等。
3,在传输用户反馈或者下载OTA升级包时,如果不是十分紧急的操作时,尽量采用压缩数据进行传输且延迟到设备充电和WIFI状态时进行。
4,在有必要的情况下尽量通过PowerManager.WakeLock和JobScheduler来控制一些逻辑操作达到省电优化。
5,对定位要求不太高的场景尽量使用网络定位,而不是GPS定位。
6,对于定时任务尽量使用AlarmManager,而不是sleep或者Timer进行管理。
7,尽可能的减少网络请求次数和减小网络请求时间间隔。
8,后台任务要尽可能少的唤醒CPU,譬如IM通信的长连接心跳时间间隔、一些应用的后台定时唤醒时间间隔等要设计合理。
9,特殊耗电业务情况可以进行弹窗等友好的交互设计提醒用户该操作会耗用过多电量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值