android的性能优化和应用体验改善

这里指的性能优化不是系统本身启动速度之类的优化,而是对于普通app而言。

通常apk编译之后,如果是系统默认应用,开启ODEX enable之后编译,会生成apk和odex文件,前者包含了资源文件和签名信息,后者则包含了优化过的代码。如果是eclipse或者ant等三方工具生成的apk,则会在第一次安装进手机的时候生成odex放在/data/diavik-cache目录下

由于android采用了dalvik虚拟机,所以和java一样,由于是解释性语言,所以运行的时候相当于翻译了一下再传递给cpu执行。在现在的art虚拟机下,这部分工作已经在编译的时候完成了,我们看到的odex文件中其实已经包含了机器码模式的执行文件。所以最大的性能优化不是来自于应用本身,而是手机系统的更新。。。

当然如果系统不能随便换,那只好牙缝中扣肉了,抠一点是一点吧。

先说下最常用的方法:源码的优化

1.在非常频繁调用的函数中尽量少创建对象,而是重复使用已经的对象,这跟c里面不断malloc、free一样。
2.如果涉及到需要频繁调用,涉及到时效性的多线程应用,尽量不要用锁去控制互斥,因为这会极大降低速度。建议使用环形buffer,或者其他安卓的一些FIFO类,比如Queue的变种,虽然后者可能也是使用了互斥变量。
3.经常去看看不同版本的安卓系统之间api的区别,毕竟新的api总是会比老的高效,那些大牛比我们强不知道几个等级。。
4.如果涉及到数据库大量数据的转换排序,比如拨号键盘联系人姓名匹配,不要吝啬空间,这时候增加排序字段,由insert记录的时候去填写比取的时候要快很多,也就是空间换时间的做法。
5.Java的反射机制在性能重要的地方最好只是调用invoke(),而不是每次都是取类。
6.使用HashMap之类的列表进行查找时,如果键是自定义的对象,要优化equals以及hashCode方法。因为他们匹配key的时候要调用到。
7.涉及到JNI开发中的c++或者c的代码优化,这个比较多,属于c的知识,可以自行查看,什么结构体字节对齐之类的一坨。
8.程序中的死循环当然是不行的,会直接让系统玩完。虽然这个错误很少犯,不过可能有时判断条件有问题也会出现。
9.注意数组之类的在释放时,要设置成null。
10.如果使用了大内存,尽量不要频繁在主线程中调用GC,否则会很慢。

然后是android一些自己的特性优化:

0.减少布局的重叠,这个很重要,越复杂的布局越需要时间,尽量保持扁平化。
1.如果想尽早接收到系统广播,可以设置manifest中的接收优先级。
2.如果想让线程优先级高一点,得到更多的时间片,可以在代码中加入Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);之类的调用,会很有效。当然不能乱加。。
3.UI线程切记不能干费时的工作,否则会弹出ANR,也就是那个等待框。如果有需要可以启动新的线程,甚至线程池。
4.Broadcast中也是类似,如果有必要起service来执行。
5.文件解析之类的通常都是瓶颈,所以尽量使用缓存,不要去经常执行文件IO。
6.有些新的类很有用,比如RecyclerView,比如okhttp,比如Jackson 框架。这些都是各位神人免费
帮我们封装好的东西,不用白不用。
7.对于背景图片,即background最好是少用,比如Listview中,在没有获取到对应的bitmap的时候,可以设置为透明,获取到了之后再填充图片。因为渲染是需要资源的。
8.Android提供了很多不同的容器,比如ArrayList、Vector、Queue等等,但是他们适用场景并不一致,在高数据量的情况下表现也不一致,所以我们需要选用合适的类来处理我们的大量数据。

然后是尽量让应用不被kill:

因为大家都知道安卓后台切换到前台很快,但是如果是已经被杀。。启动就很慢了,用户体验就不太好。任何系统的内存都是有线的,虽然现在2g ram的配置已经比比皆是,但是如果涉及到编解码之类的东西,其实还是很耗的。
安卓杀进程是由lowmemorykiller来执行的,其实是根据linux的管理机制改装过来的,每个进程有个adj值,然后系统中维护了一个杀进行的阀值,比如少于多少杀后台进程,这个另外再说。所以我们程序如果不想被没事杀掉,特别是处于后台的时候,就得尽量避免占用过多内存,同时告诉系统我这个是“特殊”的,尽量不要杀我。
1.对于在platform上编译出来的apk,绑定为system签名并且将自己设置为persist或者干脆进程跟phone之类的同个是最理想的,这样基本永远不会被杀。
2.如果是第三方apk,监听一些常见的,比如NETStatus改变或者TIME改变之类的intent,可以不断检测自己有没有被杀掉。
3.如果是后台service,可以new一个Notification并设置为foreground来增加优先级。

然后是布局方面的优化:

1.横向布局,减少布局层数。这能提高应用反映速度
2.减少布局中创建的对象。使用尽可能少的对象来布局
3.在布局嵌套时,考虑上层的布局方式,看是否能用merge来减少一层布局
4.使用推迟初始化布局—-ViewStub
ViewStub只需要在代码中,findViewById 然后inflate就可以

然后是OOM之类的避免和网络图片显示速度的加快
1.在ListView和GridView等场景下,如果同时在一屏幕里显示几十张图片,很容易发生OOM。这时候一般采用缩略图的显示方式来避免这种情况,通过读取图片的长宽和调用Bitmap.createScaledBitmap方法来构建缩略图。

2.网络图片可以采用本地磁盘缓存的方式,首先读取自己的缓存目录,判断是否图片存在,如果不存在再通过开线程池去远程取。

3.对于不需要保存或者性能要求高的应用,可以采用LruCache等缓存,来存储图片。做到一定大小的缓存中循环使用。

4.记得不用的bitmap一定要手动recycle。

然后是一些用户层面设置可以带来的优化:

1.提供多个图片质量设置的权力给用户,这样可以节省流量也可以提高显示速度。
2.使用被动定位服务
3.一些提示性的功能需要给用户直观的取消界面,否则会造成困扰。
4.如果这个应用是不想被休眠的,就使用wakelock来控制。

然后是框架的选择:

是纯native代码开发还是混合html开发,这是个问题。个人感受,html开发主要在很多数据的列表滚动,以及seek条这些地方比较有性能上的问题,毕竟js处理的东西可能性能上没这么好,其他的一般应用还是主要看自己的费用及使用场景来选择吧。服务器端,php+mysql便宜好用,不过访问量大的话也许SSH+Oracle更加合适。当然更多的分布式负载均衡之类的太多了,也不太了解,不说了。

内存泄漏检测

最后来说下内存是否泄漏的检测,Java的内存回收机制保证了一个内存对象只要还有引用计数,则不会被GC。我们有时候会new出来很多个线程却忘记销毁,或者new出来不少socket却忘记关闭,这些东西就永远留在内存中无法被回收了。

android有很多现成的工具来查看当前进程所占用的内存大小,虽然并不是非常精确,具体可以直接参照这个博文:http://blog.csdn.net/hudashi/article/details/7050897

另外MAT这个工具据说可以用来检查内存泄漏。不过我没用过,大家可以参考下。

以上是自己平时工作用到的一些总结,下次有新的继续。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值