当前位置: 首页 > 科技观察

浅谈Android中的性能优化

时间:2023-03-17 23:52:03 科技观察

性能优化是一个很大的范畴。如果有人问你如何在Android中进行性能优化,你可能会不知从何下手。首先要明白为什么我们的app要优化,最明显的时刻:用户说,whatshit,刷了这么久没反应,取消卸载就好了。这和它有什么关系?让我们苍白地反驳它。尼玛用户设备老旧,网络不好。关我什么事,根本没必要优化。但是老板做了一个决定,给CTO施压,然后CTO又来找你:我今天必须想办法优化Y的,不然不让回家。那么,为什么从UI的外观来看,App卡住了,缓慢且混乱。让我们尝试剖析它。题外话:把minSDK改成4.0+,去他妈的低端用户,连手机都不愿意换,还能指望它能给你带来多少收益,就pass吧。4.0之前的系统bug很多,不能为了弥补这些bug而降低整体的高性能。好吧,我们先从UI说起:首先我们要了解的是UI的绘制过程:measure-layout-draw,measure和layout需要for循环的所有子控件,组装起来完成绘制和布局。因此,子控件越多,耗时越长(inflate、layout_weight、relative、多层嵌套等),减少不必要的子控件或层级是相当有必要的。可以通过merge、viewstub等标签减少层级嵌套。如果你的空间概念不太好,可以使用HierarchyViewer工具来查看。对于Listview或GridView等有多个item的组件,复用item可以减少inflate的次数,通过setTag和getTag的ViewHolder方法实现复用。这里需要注意的是,holder中的控件最好重新设置后再赋值,避免图文乱码。ViewPager在首次显示时和左右滑动时有几种优化方法:ViewPager同时缓存的页面数最好是最小值3,如果过多pages,ViewPager初始化的pager会很多,所以pager的累计渲染时间会增加,好像卡住了。每个寻呼机只应在显示时加载网络或数据库(UserVisibleHint=true)。最好不要预加载数据,以免造成无法显示或加载时间过长的浪费图片。我应该怎么办?它分为两部分,下载速度和加载速度。对于下载,需要控制同时下载的最大任务数(平均速度较慢),在InputStream中加一层缓冲流(如BufferedInputStream)会更快。关于加载速度,我们需要知道一件事。虽然下载的图片可能只有几百K,但是解码成位图占用的内存却可以成倍增加。尽可能缩小图片的尺寸是根本因素,这样服务器才能提供不同的分辨率。图片是最好的解决方案。总会有内存耗尽的时候。不要总是认为高分辨率会更清晰。其实只有150*150的空间。1000*1000的图片不太合适。的。另外,在加载速度方面:内存>硬盘>网络,内存缓存的合理使用也是关键。如果你写得不好,也没关系。开源的图片缓存框架那么多,不用自己操心。再说缓存的缓存方式有很多种,在Stay中就不用一一列举了。我们想说的是将它们一起使用。比如我们过去一直在使用强引用和HashMap。后来我们发现它很占内存,所以我们及时使用了软引用和弱引用进行回收。后来因为回收机制不可控,引入lrucache,通过算法平衡disklrucache。内存和硬盘缓存。随着android版本的进步和进化,我们也应该拥抱变化。如果你的App中存在软引用和弱引用,不妨再检查一下。比如网络+数据库。我们通常主动获取互联网,而不是被动接受互联网。那么如果数据重复或不变怎么办?那取一次网络数据有什么意义呢?我的解决方案是给每个activity或者fragment或者每个component设置一个最大请求间隔,比如listview,第一次请求数据的时候,保存一份到数据库,记录下时间戳。下次重新初始化时,判断是否超过最大时间间隔(如5分钟)。如果没有,只加载数据库数据,不需要再做网络查询。当然也有一些隐式的http请求框架会缓存服务器数据,在一定时间内不再请求网络,或者服务器返回304时直接返回之前缓存的数据。反正我们也讲了网络,所以说一下有很多现成的HTTP框架供我们使用。我们几乎只需要写配置就可以处理一个url请求,但是有很多东西需要服务器配合,比如:json数据格式,WebP代替jpg,支持断点续传,将多个请求合并为一个,尽量不要做重定向,服务器缓存和负载平衡等。对于客户端本身,除了上面的实现之外,我们还需要合理的缓存,控制最大并发请求数,及时取消无效请求,过滤重复请求,超时时间设置,请求优先级设置等优化不一个人的工作实现一个功能很容易,但是优化和重构就不容易了。需要多方面的预测和联调。合理的假设和实践是最重要的优化手段。说完这些具体的点,再来说说一些常识,或者说代码规范。你要知道不要在for循环中声明临时变量,除非万不得已不要在里面写trycatch。了解垃圾回收机制,避免频繁的GC、内存泄漏、OOM(有机会再说),合理使用数据类型,比如StringBuilder而不是String,(最常见的笔试题有几个str+="str")中的对象,少用Enumerate枚举,少用父类声明(List,Map)如果经常新建线程,最好通过线程池执行,减少线程创建开销。您需要了解单例的好处并正确使用它。多使用常量,少显式“action_key”,维护一个常量类,不要重复声明这些常量。如果可以的话,至少了解一下设计模式中的策略模式、组合模式、装饰模式、工厂模式、观察者模式。这些可以帮助你合理解耦。即使需求经常变化,也不用害怕全身而退。需求变更并不可怕,可怕的是写代码之前没有合理的设计。当然,还有很多很多。Stay说的只是一个大纲,还需要继续尝试。会开发写代码和会做产品是有很大区别的。态度可以杀死80%的程序员。当你遇到一些需要优化的地方,耐心分析,时间的积累会让你成为真正的工程师。另外,优化没有绝对的完美。每次优化都是基于当前环境进行的。你必须明白沟通是最好的优化。如何在Android上做性能优化?写了三年左右的代码,差不多就可以知道了。原文链接:http://www.cnblogs.com/stay/p/4784014.html