那些Android中的性能优化


性能优化是一个大的范畴,若是有人问你在Android中如何作性能优化的,也许都不知道从哪开始提及。android

首先要明白的是,为何咱们的App须要优化,最显而易见的时刻:用户say,什么狗屎,刷这么久都没反应,取关卸载算了。算法

这跟什么有关,咱们先苍白的反驳下,尼玛用户设备老旧网又烂,关我屁事,根本不用优化。但是,老板拍板了,施压给CTO,而后CTO又来找你:Y的今天必须给我想办法优化了,否则不许回家。数据库

好吧,为何从UI的表象上看,App又卡又慢并且还错乱。咱们试着来剖析下吧。json

题外话:把minSDK改到4.0+,去特么的low用户,连手机都不肯意换,还能期望它能给你带来多少营收么,直接pass掉吧。4.0前的系统bug很多,不能为了弥补这些bug而下降了总体的高性能。设计模式

好了,让咱们先从UI提及:缓存

首先要明白的是UI的绘制流程measure-layout-draw,measure与layout都须要for loop全部的子控件,聚集起来才能完成绘制,布局。因此子控件越多,所消耗的时间越长(inflate,layout_weight,relative,多层嵌套等),减小没必要要的子控件或层级,是至关有必要的。你能够经过merge,viewstub这些标签来减小层级嵌套。若是你的空间观念没那么好,能够用HierarchyViewer工具来检查。性能优化

对于Listview或者GridView这种多item的组件来讲,复用item能够减小inflate次数,经过setTag,getTag的ViewHolder方式实现复用,这里要注意的是,holder中的控件最好reset后再赋值,避免图片,文字错乱。服务器

对于ViewPager第一次显示时卡顿以及左右滑动卡顿,有如下几种优化方式:网络

    • ViewPager同时缓存page数最好为最小值3,若是过多,那么第一次显示时,ViewPager所初始化的pager就会不少,这样pager累积渲染耗时就会增多,看起来就卡。并发

    • 每一个pager应该只在显示时才加载网络或数据库(UserVisibleHint=true),最好不要预加载数据,以避免形成浪费

图片显示不出来或者加载时间太长,怎么办?分两部分,下载速度,加载速度

    • 对于下载,要控制好同时下载的最大任务数(平均速度慢),同时给InputStream再包一层缓冲流会更快(如BufferedInputStream)。

    • 对于加载速度,咱们要知道一点,虽然下载的图片可能只有几百K,可是decode成bitmap所占用的内存但是成倍的,尽量的减少图片size是根本因素,让服务端提供不一样分辨率的图片才是最好的解决方案,内存总有耗尽的时刻,别老想着大分辨率会更清晰,实际就只有150*150的空间,非给弄张1000*1000的图片是不恰当的。另外论加载速度:内存>硬盘>网络,合理的使用内存缓存也是关键。假如本身写很差,不要紧,有那么多开源的图片缓存框架,不用本身操心。


再说缓存

有不少种缓存方式,也不用Stay列举了,咱们要说的是搭配使用。

    • 比方说,之前咱们一直在用强引用,HashMap,后来咱们发现占内存,咱们就用软引用,弱引用来及时回收,再后来由于回收机制不可控,因此又有了lrucache,disklrucache经过算法来平衡内存与硬盘缓存。随着android版本的推动与演化,咱们也应该拥抱变化。若是你的App里还有软引用,弱引用的地方,不妨再check下。
    • 比方说网络+数据库。网络咱们通常都是去主动获取,而非被动接受。那若是说数据是重复的或者未更改的呢?那咱们去取一次网络数据有什么意义呢?个人解决方案是给每一个activity或fragment或每一个组件设置一个最大请求间隔,好比一个listview,第一次请求数据时,保存一份到数据库,并记下时间戳,当下次从新初始化时,判断是否超过最大时间间隔(如5分钟),若是没有,只加载数据库数据,不须要再作网络请求。固然,还有一些隐式的http请求框架会缓存服务器数据,在必定时间内再也不请求网络,或者当服务器返回304时将以前缓存的数据直接返回。

反正也说到网络了,那咱们也来讲说

    • 如今有不少现成HTTP框架供咱们使用,咱们几乎只用写配置就能够搞定一个url请求,可是这里有不少须要服务端配合的,好比:json数据格式,WebP代替jpg,支持断点续传,多个请求合并成一个,尽可能不作重定向,服务器缓存以及负载均衡等。

    • 对客户端自己,除了上述的实现,咱们还须要合理的缓存,控制最大请求并发量,及时取消已失效的请求,过滤重复请求,timeout时间设置,请求优先级设置等。

优化可不是一我的的事,实现一个功能简单,可是想优化重构,那是很不容易的事。须要多方面的预判与联调。合理的假设与实践是优化最重要的手段。


说完这些具体的点,咱们再来讲说一些常识,或者称之为代码规范。

    • 你要知道for loop中不要声明临时变量,不到万不得已不要在里面写try catch。

    • 明白垃圾回收机制,避免频繁GC,内存泄漏,OOM(有机会专门说)
    • 合理使用数据类型,好比StringBuilder代替String,(笔试题最多见的是str+="str"中有几个对象) ,少用枚举enum,少用父类声明(List,Map)

    • 若是你有频繁的new线程,那最好经过线程池去execute它们,减小线程建立开销。

    • 你要知道单例的好处,并正确的使用它。

    • 多用常量,少用显式的"action_key",并维护一个常量类,别重复声明这些常量。

    • 若是能够,至少要弄懂设计模式中的策略模式,组合模式,装饰模式,工厂模式,观察者模式,这些能帮助你合理的解耦,即便需求频繁变动,你也不用惧怕牵一发而动全身。需求变动不可怕,可怕的是没有在写代码以前作合理的设计。

固然还有不少不少,Stay所说的也只是一个大的轮廓,仍是须要本身不断的尝试。会开发写代码跟会作产品的区别仍是蛮大的,仅仅是态度就能刷死80%的码农了。当你碰到一些须要优化的地方,耐心的去分析,时间的累积会让你成为真正的工程师。


另外优化也没有绝对的完美,每一次优化都是基于当前的环境来作的,要明白沟通是最好的优化,不盲从,不随便,三思然后行。

Android上如何作性能优化的?大概写三年代码就能差很少知道了。

相关文章
相关标签/搜索