Android开发中的性能优化(摘录:陈彧堃演讲实录)

  大家好!我是陈彧堃,其实HTML5我之前也做过一些相关的研究,包括现在我们也在做一些调研。我个人一年前在G3上利用HTML5开发一些东西的时候,我发现原生的对HTML不支持,开始踏踏实实做Android原生代码开发。目前来说在将来一到两年内HTML5的东西会慢慢侵蚀原生程序,我讲的是现在进行时,现在来说Android开发还是占绝对主导地位。所以今天来看一下Android研发的优化。

  我想做一个小调研,有多少人知道友盟?谢谢!感觉不是很多。简单介绍一下我们是一个面向中国移动开发者的服务平台,我们最核心、推出最久的功能是一个统计平台,提供SDK,支持全平台,服务了八千以上的移动厂商,包括了超过一万五千个移动应用。同时我们还会定期发一些报告,这些报告我们希望对产业链中不同的、向开发者、应用商、产业链其他部分合作伙伴都有一些参考作用。

不同的应用,出的各种各样的问题,最终归根到底都是由于体验问题。找到了用户体验问题,就看一下开发难点,最后提出一些优化策略。最后我们提一下代码复用问题。

  首先搞清楚关注的东西。大家对这个图应该很熟悉吧?这是Android的体系架构图。蓝色的上面部分是平时关注最多,基本上都是Java代码,Android是基于MID开发的,在这个上面提供一些库,这些库是纯C++的,如果要调的话是向上面提供API,同时Android提供了虚拟层,这比较类似于,但是是不同的界面,因为有这个虚拟层,做Android开发的时候不需要考虑太多内存方面的东西,正是由于这个原因导致很多JAV程序员转做Android的时候,他们会认为不需要考虑性能优化的问题。其实这是非常错误的认识。

  在Android上开发都和传统的Web开发、Java开发不太一样,所以我们做开发的时候需要更多考虑跟Android手机有关系的设计和优化。从用户体验出发讲三点,第一是用户要求快速,因为手机上主要访问数据,所以数据的获得,有几个途径,第一是内存,五毫秒去一个数据。我也有一个内存文件、一个数据库,还有传统IO。这个需要上百毫秒的时间,IO需要这边去桌上拿,时间也不是很长。如果你的程序很慢,用户会马上看到一个系统提示框,说这个没有响应,是不是应该关掉,如果用户关掉之后应该卸载,卸载完之后还不够,还给你几个差评,给你一个一星,别人看到这个以后可能再也不会下载这个程序。你可能需要找很多水军把一星的评论刷掉。这是很不好的体验。

  第一点是需要快,第二点需要友好。我们一定要保证用户操作流畅、自然。Android上面还有一个问题是UI问题,Android机型特别多,但是Android提供很多系统级优化策略,帮助我们避免这些问题。不要涉及一些太复杂的提示去挡着用户。因为Android特别开放,现在智能手机都比较开放,像刚才讲的2.0,也有一个用户通知,如果这个太滥,也会让用户反感。不要完全照搬iOS设计,Android有很多自己的特点,有菜单键、返回键,管理都是和iOS不太一样的地方。

  Android上有一个返回键,很多iOS设计师过来的时候会把iOS菜单键,把那个设计直接带过来用,直接无视Android的按钮,打破了用户预期,他会觉得无所适从,所有系统原生程序充分利用了返回键。所以我们要尊重用户期望,满足他的心理期许。

  关系到用户体验的第三点是一定要省电,一个手机如果需要每天都充电,算不算一个移动设备?我觉得不算。首先要避免一些复杂算法,我有朋友曾经在Android手机上实现过哈析表,是谷歌这种大公司做Email,还是一个分级的,这个Email先做哈析然后再哈析,他做完以后得意。但是用户发现,当他打开应用的时候,系统会发现耗电量太大了,没过几天他就自己更新了,省了很多电,性能没有受太大的影响。手机上真的不要涉及太复杂的算法。

  因为多进程、多限程,并且Android没有退出的设计,所以可以设计一个永远在后台跑的,推出一些信息、提供一些时间。我建议考虑一下实时和非实时两种不同需求。如果实时建议使用谷歌的功能。如果是非实时的需求,建议一定要延长推崇时间,比如隔几个小时、一天扑一次。而且时间可以设置得灵活一些。五比如说设了一个更新的键,可以放一个字段,这个字段代表更新周期,每次更新的时候先把字段做好。可以应付一些一会儿很紧,在你需要平台更新的时候更新,不需要的时候把时间限制设长一些。

还有网络请求不要太长,平均每个用户使用时长一分钟,现在在Android手机上一次GPS请求(中国移动基本上2G比较普遍)一次10秒以上比较普遍,一次连接20秒,三次连接用户就关闭了。所以不要频繁请求。可以结合一些压缩方式来减少网络次数。

(我认为如果要想做好Android开发,一定要能够访问国外的论坛和高手切磋。因为国外的论坛,上面有最先进、最前沿的Android技术)

  第二点适配问题,分几个问题,硬件、分辨率还有OS。Android手机有各个价格位的。我们有一个合作伙伴Camera360,他们说在做拍照的时候,需要对不同摄像头做了大量优化,有的是200万像素、有的上千万像素,对图片处理完全不一样。这是比较痛苦的事。

  然后看一下分辨率,这是二季度的总结,没有一个手机分辨率占主导地位,最多的是800×480,也只占30%不到的比例。剩下的不同分辨率千奇百怪,现在在中国Android量很大,不可能忽略一个很怪的分辨率,魅族的980×640,但是占6%的比例,所以没有办法忽略。

  这是最近的关于Android分裂的图,据统计在18个Android设备中,7个不用最新版Android,12个使用最新版短于一周,10个落后最新版两代,15个没有运行Android 3.0。

还有内存管理,Android里内存管理是非常难的问题,对于每个内存限制24M,而老式手机上限制16,这种概念大家看好像比较大,但是实际上应用本身会超过十兆,分的内存空间已经非常少,如果你做一些图片应用,拍几张照,直接读出来是长跟宽,一张照片一般都是1兆以上。所以经常会出现out of Memory问题。我们怎么解决这个问题呢?从几个方面解决,首先从视图方面优化。我们善于运用Android提供的工具,谷歌提供了分析视图结构,提供一些建议。FrameLayout不要滥用。不要超过13层嵌套,不要超过80个view。还有一个工具是TraceView,函数单独化时间是多少,这个函数包含所有的子函数的时间是多少。其实谷歌提供非常非常丰富的开发辅助工具,还有很多没有讲到,比如一个随即测试界面的程序。

  怎么减少View以及View的嵌套层次呢?左边是一个图,右面是上下两行文字。有两种写法,一种是把文字包起来,另外一种是写两行文字,设一个相互关系。看上去没有太大的差别,但是看一下树,如果用嵌套,子模块结构变化这样,如果不用嵌套,相对位置关系就变化成这样。如果只有这条没有任何问题,但如果模块被大量应用在列表里,会导致主线会经常变得很慢,如果滑动的时候会变得很卡。这些是一些小细节。

  还有一个问题是图片当中,Android提供一个技术,可以把图局部放大,如果直接拉伸,因为每个像素均匀拉伸,那么边角会变得模糊。怎么样从左边无缝拉伸到右边?简单介绍一下这个原理,一张图通过这个工具,把图定义成两个区域,第一是左边和上边的投影,投影到中间会决定你的内容,下面和右边,投影出来的内容会决定你的PNG。小图放大的问题是被均等放大,放大之后变得特别猛,画两条黑线,制定上面和左边,决定了拉伸的区域。边缘不拉伸了。就这个意思。就能产生上面的效果。

  还有更复杂的,左边这张小图怎么变成右边的图?可以指定不同的复合区域。编辑图片压缩会带来很大的优势,如果处理得好,可以省很多apk大小,下载apk的时候下载率会大幅度提高。做过一个不太精准的统计,下载率50%左右,一半情况会失败,失败情况是因为包太大。图片压缩是很重要的技术。

  另外从分辨率上适配,刚才说了系统会提供一些手段帮你做适配。提供几种不同的文件夹,ldpi、mdpi、hdpi,代表三种不同精度,系统会自己分析精度做定位。另外要尽量多使用dp,跟当前设备有关系的一个像处理。Pixel有问题,他们往往想直接用,用PS,Android里不一样,Pixel里有什么问题?有一句话叫supports 想问开发者你的程序适不适配于小屏幕、大屏幕、中屏幕,如果选择否,系统认为你没有经过特殊的配置,这时候会出什么问题?比如800×480的设备,通过大分辨率,会转化为533×320,因为使用了API。他认为你画的点,其实想画在15ph、15px这个点,因为他想帮你做适配。这个时候读API会读错,所以尽量不要用pihel,不要用绝对布局。

  内存方面的优化,其中一个很大的优化是图片优化,大家知道Bi图直接读大小是X×Y,我们要自己压缩,设一下压缩率就可以了。做应用的很多很多问题,跨写、包括M,其实很简单,可以写很多东西。

  还有就是要了解编译器的优化原则。某种程度上是反OO的问题,不要太多用getter和setter,包括访问速度都有一系列的问题。

  另外说一下关于C++开发,铁峰也讲了,C++的确某些场景下会提升性能,这个领域是游戏。如果普遍应用想用C++就需要慎重,除非有特别好的C++高手,包括C的代码也不可以做优化,那时候很多东西,做出来还不如全部用加法写速度快。

  另外下载的时候一定要有buffer。我们的经验是,因为我们做SDO,做了很多数据压缩方面的探索,结合两种技术会导致网络发送数据包大小变成原代码的30%左右,这是非常省流量和减少失败率的方法。别人看代码的时候会出现一些小问题。其实我认为更大的好处还是在于降低了APK大小,可以提升APK下载成功率。

最后再说一下当我们写很多代码之后怎么样复用代码。最传统的做法和JAVA没什么区别,优点是稳定,但是缺点是无法集成资源文件。

  Android提供了一个新的复用,叫Android Library。第一步是先创建Library工程,别人可以直接用这个工程,不用管资源什么东西。也有一个问题,它的习惯问题。现在开发者不太习惯这种机制,并且会有资源冲突。所以大家要根据自己开发习惯和项目实际情况去考虑这个问题。

  最后就是讲一下客户端的技术,最后比拼的还是服务。所以掌握服务器开发很重要。个人推荐大家掌握一个容易上手的。其实最终大家拼的还是一个互联的一种服务,而不是客户端做得如何漂亮。

  另外客户端可能进行一些比较复杂的计算的时候,要深思熟虑一下,你的计算是不是一定要做,是不是数据经常需要更新,如果是的话需要把这个东西放在服务器端啊,服务器端跟客户端涉及一套协议。但如果发展起来之后,这个问题可能不存在,但是目前来说,要根据自己的业务来决定选择什么样的BS2、CS2。

  综合来看,第一点要跟tracrace和monkey结合测试,然后写代码,最后做好代码复用,精通一门服务器开发构架,尽快变成服务器端构架应用。最后以运用的心态经营应用。为什么呢?说到运营的话,必须要了解,我们有提供了解用户的一种机制,我们是一个非常专注了解帮助开发者了解应用的各种使用情况,包括收集你的crash报表,告诉程序员最容易犯的错误是什么,我们也提供一种双向反馈系统。我们提供一个界面,用户可以通过界面提交反馈,他觉得你有什么不好给你建议,在我们网站上可以看到这个建议,看到建议之后可以给他回复,用户第二次启动应用会看到这条回复,建立了用户和开发者之间双向的渠道。从而提供一些应用联盟做推广,交叉推广的工具。

  如果大家有兴趣可以访问我们的网站和微博,谢谢大家!

posted on 2012-04-27 16:14  Devin Zhang  阅读(1658)  评论(0编辑  收藏  举报