android app 开发过程中 对于性能优化的总结

一款手机应用  从开发过程中就要做好 性能优化,这样才能 让用户体验度 提升, 假如 我们打开一个应用 出现卡顿, 不流畅,则会很影响 用户对该应用的态度,产品狗 都很注意这些人机交互方面的 体验。

谷歌官方也是一直在优化 android 系统,不论是  碎片化处理 还是 系能 上面,这方面 ios 就做的比较好,配置比 android 低,但是流畅度却比android高,体验效果更好。

官方推荐方案:http://www.oschina.net/news/60157/android-performance-patterns

具体从开发中 我总结了几大方面, 以便于让应用更流畅。

应用程序的性能问题 往往体现在很多方面, 比如应用程序第一次启动速度慢,或者进入某一界面速度慢;启动某一有动画效果的界面,动画执行过程不流畅,或者动画执行卡顿时间长;ListView列表滑动过程中卡顿,不流畅;应用程序自定义的某特定界面执行速度慢,例如Launcher应用桌面左右滑动效果不平滑;响应某一用户事件时长时间无响应(ANR);操作数据库时,执行大量数据的增删改查操作,执行速度慢;应用长时间运行后,随机出现卡顿现象。

以上的问题的原因可能不只一个,并且很多情况下并不是应用本身的问题,也有可能是系统其他层次有问题,只不过体现在应用层。所以说应用层总是首当其冲,开发人员在处理 性能问题时,需要做的第一件事情就是判断是否是应用自身引起的性能问题,然后再对症下药;但有些时候应用本身逻辑正常,明显是系统的硬件配置不足引起,此时就要根据产品或项目需求,采取一些更加激进的方式优化性能,以弥补硬件配置的不足。

以下从几个不同的角度总结一下应用程序性能优化的一些方法。

一、编程思想上

应用层的性能优化通常可以从以下几个方面考虑:

1. 了解编程语言的编译原理,使用高效编码方式从语法上提高程序性能;

2. 采用合理的数据结构和算法提高程序性能,这往往是决定程序性能的关键;

3. 重视界面布局优化;

4. 采用多线程、缓存数据、延迟加载、提前加载等手段,解决严重的性能瓶颈;

5. 合理配置虚拟机堆内存使用上限和使用率,减少垃圾回收频率;

6. 合理使用native代码;

7. 合理配置数据库缓存类型和优化SQL语句加快读取速度,使用事务加快写入速度;

7. 使用工具分析性能问题,找出性能瓶颈;

当然肯定还有很多其他的性能优化方法,此处仅列出一些经常会用到的方法。

二、编程技巧

(一)Performance Tips (For Java)

Google官网上有一些关于应用程序性能提升的技巧,之前公司内也有很多总结提到过,在此简单罗列一下,详细内容可以从官网获取。

http://developer.android.com/training/articles/perf-tips.html

需要说明的是,文章列出的优化技巧主要是一些微小的性能提升,决定程序整体性能的仍然取决于程序的业务逻辑设计、代码的数据结构和算法。研发人员需要将这些优化技巧应用到平时的编码过程中,积少成多,也会对性能有很大的影响。

写出高效的代码需要遵循两条原则:

不执行不必要的操作;

不分配不必要的内存;

两条原则分别针对CPU和内存,完成必要操作的前提下尽可能的节省CPU和内存资源,自然执行效率要高。单纯这样说听起来很虚,毕竟没有一个统一的标准判断什么是必要和不必要的,需要结合具体情况具体分析了。

1. 避免创建不必要的对象

创建太多的对象会造成性能低下,这谁都知道,可是为什么呢?首先分配内存本身需要时间,其次虚拟机运行时堆内存使用量是有上限的,当使用量到达一定程度时会触发垃圾回收,垃圾回收会使得线程甚至是整个进程暂停运行。可想而知,如果有对象频繁的创建和销毁,或者内存使用率很高,就会造成应用程序严重卡顿。

2.合理使用static成员

主要有三点需要掌握:

如果一个方法不需要操作运行时的动态变量和方法,那么可以将方法设置为static的。

常量字段要声明为“static final”,因为这样常量会被存放在dex文件的静态字段初始化器中被直接访问,否则在运行时需要通过编译时自动生成的一些函数来初始化。此规则只对基本类型和String类型有效。

不要将视图控件声明为static,因为View对象会引用Activity对象,当Activity退出时其对象本身无法被销毁,会造成内存溢出。

3. 避免内部的Getters/Setters

面向对象设计中,字段访问使用Getters/Setters通常是一个好的原则,但是在Android开发中限于硬件条件,除非字段需要被公开访问,否则如果只是有限范围内的内部访问(例如包内访问)则不建议使用Getters/Setters。在开启JIT时,直接访问的速度比间接访问要快7倍。

4. 使用for-each循环

优先使用for-each循环通常情况下会获得更高的效率;除了一种情况,即对ArrayList进行遍历时,使用手动的计数循环效率要更高。

5. 使用package代替private以便私有内部类高效访问外部类成员

私有内部类的方法访问外部类的私有成员变量和方法,在语法上是正确的,但是虚拟机在运行时并不是直接访问的,而是在编译时会在外部类中自动生成一些包级别的静态方法,执行时内部类会调用这些静态方法来访问外部类的私有成员。这样的话就多了一层方法调用,性能有所损耗。

一种解决这个问题的方法就是将外部类的私有成员改为包级别的,这样内部类就可以直接访问,当然前提是设计上可接受。

6. 避免使用浮点类型

经验之谈,在Android设备中浮点型大概比整型数据处理速度慢两倍,所以如果整型可以解决的问题就不要用浮点型。

另外,一些处理器有硬件乘法但是没有除法,这种情况下除法和取模运算是用软件实现的。为了提高效率,在写运算式时可以考虑将一些除法操作直接改写为乘法实现,例如将“x / 2”改写为“x * 0.5”。

7. 了解并使用库函数

Java标准库和Android Framework中包含了大量高效且健壮的库函数,很多函数还采用了native实现,通常情况下比我们用Java实现同样功能的代码的效率要高很多。所以善于使用系统库函数可以节省开发时间,并且也不容易出错。

(二)布局性能优化

布局直接影响到界面的显示时间。关于界面布局的性能优化在技术上并没有难点,个人认为最重要的是是否认识到布局优化的重要性。起初我也会觉得布局本身不会是性能瓶颈,并且也很难优化,好不容易写了复杂的布局文件,或者原生代码就是那样,而且也用log查看了setContentView的时间,似乎没什么问题,实在是不想去研究。但实际上布局问题没有想象的那么简单。

布局的性能优化之所以重要,因为以下两个方面:

·           布局文件是一个xml文件,inflate布局文件其实就是解析xml,根据标签信息创建相应的布局对象并做关联。xml中的标签和属性设置越多,节点树的深度越深,在解析时要执行的判断逻辑、函数的嵌套和递归就越多,所以时间消耗越多;

·        inflate操作只是布局影响的第一个环节,一个界面要显示出来,在requestLayout后还要执行一系列的measure、layout、draw的操作,每一步的执行时间都会受到布局本身的影响。而界面的最终显示是所有这些操作完成后才实现的,所以如果布局质量差,会增加每一步操作的时间成本,最终显示时间就会比较长。

那么布局如何优化?总结如下几点:

1. 遵循一条规则:布局层次尽量少

也就是说,在达到同样布局效果的前提下,xml文件中树的深度尽量的潜。要做到这一点需要合理的使用布局控件:

典型的情况是你可以使用RelativeLayout来代替LinearLayout实现相同的布局效果;

还有一种是如果布局树的A节点只有一个子节点B,而B只有一个子节点C,那么B通常是可以去掉的;

合理的使用<merge>标签,如果布局X可以被include到Y中,那么需要考虑X的根节点是否可以设置为<merge>,这样在解析时会将<merge>的子节点添加到Y中,而<merge>本身不会添加。

2. 使用Lint分析布局

Lint是SDK中tools目录下的工具,ADT中集成了Lint的可视化控制界面。用Lint扫描应用程序,它会从很多方面对应用进行分析,并提示那些可能有缺陷的地方,其中就包含与性能相关的内容。你可以在Google官网上了解详细信息。

http://developer.android.com/tools/debugging/improving-w-lint.html

http://developer.android.com/tools/help/lint.html

3. 使用HierarchyViewer分析布局

HierarchyViewer(以下简称HV)也是SDK中tools目录下的工具,ADT中也集成了HV的可视化控制界面。可以使用HV查看当前界面的布局,它能提供很多信息,其中有两个可以帮助我们分析性能问题:

·           HV的树视图展现了视图控件的相互关系,可以用来检查是否有第1点中提到的情况。

·          树视图中可以显示每个节点measure、layout、draw的时间,并且每一项用一个圆点表示其耗时是否正常,每个圆点分别用绿色、黄色、红色表示耗时正常、警告、危险,这样就可以很方便的找到有性能瓶颈了。如果树视图中没有显示这些时间,你可以点击“Obtain layout times for tree rooted at selected node”按钮刷新界面显示。

http://developer.android.com/tools/debugging/debugging-ui.html

4. 使用ViewStub延迟加载视图

ViewStub是一个没有尺寸大小并且不会在布局中嵌套或渲染任何东西的轻量级的视图。如果界面中有一部分视图控件不需要立即显示,则可以将其写到一个单独的layout文件中,用ViewStub标签代替,当要真正显示这部分内容时再通过ViewStub将视图加载进来。

http://developer.android.com/training/improving-layouts/loading-ondemand.html

三、工具使用

遵循好的编码习惯可以让程序执行更有效率,但是实际运行时仍然会遇到各种各样的性能问题。幸好有很多强大的工具能帮助我们分析性能瓶颈,找到问题所在。以下介绍的工具想必大家已经很熟悉了,网上有很多相关文章写的都很不错,在此不再赘述,仅对这些工具在使用时的一些关键点做一些说明。关于这些工具的详细使用方法请见网上的一篇文章:http://blog.csdn.net/innost/article/details/9008691。

(一)Traceview

做性能优化的最直接的方法,就是复现有性能问题的场景,并监控此过程中程序的执行流程,如果能够方便的分析程序中函数的调用关系和执行时间,自然也就很容易找出性能瓶颈了。

Traceview就是用来分析函数调用过程的工具,利用它可以方便的分析性能问题。它的使用方式需要以下几步:

使用Android的Debug API,或者DDMS监控程序运行过程;

复现有性能问题的场景,用第1步的方法获取程序过程中的函数调用日志文件,即trace文件;

使用Traceview导入trace文件即可;

Traceview的界面很直观,但是在分析过程中需要特别注意以下几点:

1. Profile Panel中的各列的含义:

·         Incl – 指函数本身和内部嵌套的其他函数的执行时间;

·         Excl -  指函数本身,不包含内部嵌套的其他函数的执行时间;

·         Cpu Time – 指函数执行时所占用的CPU时间片的总和,不包含等待调度的时间;

·         Real Time – 指函数执行过程的真实时间,包含等待调度的时间;

·         Cpu Time/Call – 指函数平均每次调用的CPU时间;

·         Real Time/Call – 指函数平均每次调用的真实时间;

·         Calls+Recur Calls/Total – 指函数调用的总次数+递归调用次数百分比;

·         % - 带有%的列是指函数的执行时间占总采样时间的百分比;

2. 如何分析性能瓶颈

首先通常需要关心的是CPU时间,可以找出程序自身的问题,真实时间会受到系统其他因素的影响。然后可以从四个方面进行分析:

1)分析有哪些函数单次执行时间长

可以点击“Cpu Time/Call”一列,按照降序排列,并找出那些执行时间相对较长同时也是我们关心的函数,然后再查看其函数内部的详细执行过程;

2)分析有哪些函数调用次数过多

可以点击“Calls+RecurCalls/Total”一列,按照降序排列,并找出哪些执行次数相对较多同时也是我们关心的函数,然后再查看其函数内部的详细执行过程;

3)分析有哪些函数总执行时间长

有些函数的单次执行时间不是特别长,总调用次数也不是特别多,但是二者相乘得出的总的执行时间较长,可以点击“Incl Cpu Time”,按照降序排列,找出这些函数;

4)有时我们很明确需要查看一些特定类的特定方法,可以在页面最下方的搜索条中搜索,不过好像只支持全小写输入。

3. 提示一点:利用API或工具采样trace信息时,会禁用JIT功能,同时因为采样本身也需要占用系统资源,所以用Traceview查看函数的执行时间都要比正常运行时慢不少,我们只要关心相对的时间消耗即可。

(二)dmtracedump

trace文件除了可以用TraceView分析外,还可以利用另外一个工具dmtracedump,它的功能也很强大。如果你觉得在Traceview中查找类和函数很痛苦,不妨试试这个工具。

dmtracedump是SDK的tools目录下的可执行文件,你可以查看它的帮助信息,并执行类似如下的命令:

dmtracedump -h -g tracemap.png path-to-your-trace-file > path-to-a-html-file.html

然后就可以得到两样东西,一个是各函数调用的树状图,可以一目了然的查看函数关系;另一个是可操作的html的文件,用浏览器打开就可以方便的查找你关心的类或函数。

(三)systrace

Systrace是从4.1引入的一个强大的性能分析工具,依赖于Kernel的ftrace功能,可以对系统中很多重要模块,特别是图形显示模块做性能分析。它功能包括跟踪系统的I/O操作、内核工作队列、CPU负载以及Android各个子系统的运行状况等。

Systrace的使用方法也是需要先通过Android提供的API或者DDMS开启跟踪监控模式,然后运行程序生成日志文件,最后分析日志文件即可。Systrace输出的是一个html文件,直接用浏览器查看即可。如果你使用最新版本的ADT,可以很方便的通过界面操作,不用再用命令了。更详细的内容可以在网上搜索。

四、关于性能优化的思考

性能优化是一个很大的话题,除了讨论如何优化外,还有一个更重要的就是是否需要优化。早在几十年前,就有很多关于性能优化的讨论,然后得出一个深刻的真理:优化更容易带来伤害,而不是好处,特别是不成熟的优化。在优化过程中,你产生的软件可能既不快速,也不正确,而且还不容易被修正。

不要因为性能而牺牲合理的结构。努力编写好的程序而不是快的程序。

但是,这并不意味着,在完成程序之前你就可以忽略性能问题。实现上的问题可以通过后期的优化而被改正,但遍布全局并且限制性能的结构缺陷几乎是不可能被改正的,除非重新编写程序。在系统完成之后再改变你的设计的某个基本方面,会导致你的系统结构病态,从而难以维护和改进。因此你应该在设计过程中考虑性能问题。

努力避免那些限制性能的设计。考虑你的代码设计的性能后果。为获得好的性能而对代码进行曲改,是一个非常不好的想法。在每次做优化之前和之后,需要对性能进行测量。

时间: 2024-12-28 09:30:14

android app 开发过程中 对于性能优化的总结的相关文章

分享Android NDK技术详解及应用(Android加壳图片处理性能优化)

1.课程研发环境案例源代码编译和运行环境以JDK1.7和android-sdk-23以及android-ndk-10e版本为基准, ,以下环境都适用于项目.开发工具:android studio 1.5正式版, QT 5.0,SourceInsight 3.5;其他工具:使用到了IDEA PRO工具以及www.androidxref.com网站查看分析源码.2.内容简介本课程主要讲解NDK技术的基本使用方法,如基本常用的JNI函数.Android系统中能使用的本地库的使用方法和注意事项以及GCC

在Android App开发中实现任意Java方法的拦截

在Android的App开发过程中,经常会有一些导致App进程崩溃的Framework层Bug,比如这里讲的Cookie同步引起的崩溃等问题.这种情况下,我们如果能拦截到Framework层的Api调用,对它做个包装把异常捕捉住,就可以避免这个问题了. 当时,纯Java层是做不到的,而Java中的Proxy机制也只能针对自己定义的类,系统Framework层的类就不管用了.这里面说一种通过借鉴Java的JNI机制来实现进程类任意Java方法拦截. 任何一个Java方法在C++层都对应一个Meth

Android手机内存管理与性能优化

Android手机内存管理与性能优化&JNI.NDK高级编程(JNI.Dalvik.内存监测) 课程分类:Android 适合人群:中级 课时数量:34小节课时 用到技术:Dalvik,DDMS,File Explorer,Adapter和图片处理,查询数据库和Static关键字使用及线程,JNI和NDK等 涉及项目:Android手机内存管理与性能优化,玩转JNI与NDK手机编程 咨询qq:1840215592 Android手机内存管理与性能优化详细介绍:http://www.dwz.cn/

Android Studido下的应用性能优化总结-内存优化

转载请标明出处(请勿转载删除底部微博.微信等信息): http://blog.csdn.net/Y1258429182/article/details/51176424 本文出自:杨哲丶的博客 上一篇文章总结的布局优化的问题,如果对布局优化不是很熟悉的,可以看一下Android Studido下的应用性能优化总结–布局优化, 这周一直筹划总结一下内存优化的问题,因为现在对于应用优化的文章很多,但是还是想完善一下才想分享这篇文章的,我会从项目中遇到的一个问题,通过解决问题的过程来分享知识,希望大家

Android Studio下的应用性能优化总结-内存优化

转载请标明出处(请勿转载删除底部微博.微信等信息): http://blog.csdn.net/Y1258429182/article/details/51176424 本文出自:杨哲丶的博客 上一篇文章总结的布局优化的问题,如果对布局优化不是很熟悉的,可以看一下Android Studido下的应用性能优化总结–布局优化, 这周一直筹划总结一下内存优化的问题,因为现在对于应用优化的文章很多,但是还是想完善一下才想分享这篇文章的,我会从项目中遇到的一个问题,通过解决问题的过程来分享知识,希望大家

使用ThinkPHP开发中MySQL性能优化的最佳21条经验

使用ThinkPHP开发中MySQL性能优化的最佳21条经验讲解,目前,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我 们程序员需要去关注的事情.当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能.这里,我们不会讲过 多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库.希望下面的这些优化技巧对你有用. 1. 为查询缓存优化你的查询大多数的MySQ

厦门App开发过程中应该避免的错误有哪些?

无论是在工作,还是在跑步.阅读,与朋友聚会.在微博上闲逛,App软件都是无所不在.App软件开发营销成本低,精准度高,用户粘合性强,不管是建立品牌形象的App,还是服务于具体活动的App,越来越多人重视app在品牌营销中的运用.移动互联网的兴起使个性更加凸显,用户对app的体验要求也更高,厦门app开发过程中,即使一个小错误都可能导致用户抛弃App.因此,在进行厦门app开发中应该注意避免一些错误. 1.APP设计之前没有理清使用流程.设计师设计APP的过程需要理清相关的使用流程.一款APP设计

Android手机内存管理与性能优化视频教程

课程讲师:xiao_q 课程分类:Android 适合人群:中级 课时数量:34小节 用到技术:Dalvik,DDMS,File Explorer,Adapter和图片处理,查询数据库和Static关键字使用及线程,JNI和NDK等 涉及项目:Android手机内存管理与性能优化,玩转JNI与NDK手机编程 咨询QQ:1609173918 链接:http://pan.baidu.com/s/1i3gnLEt密码:55a0

关于基于Linphone的视频通话Android端开发过程中遇到的问题

关于基于Linphone的视频通话Android端开发过程中遇到的问题 运用开源项目Linphone的SDK进行开发,由于是小组进行开发,我主要负责的是界面部分. 由于当时是初学Android开发,对前端界面没什么研究,对于项目管理也没什么研究,使用了很多控件的定义,进行了大量的重复工作,而且需要对于自己的命名具有极深的记忆,否则就会因为一时记忆失误造成巨大的问题. 尽管在开发时,在此方面投注了极大的注意力,但还是遇到了此方面的问题,浪费了大量的时间. 而后了解到各种设计模式,例如MVC, MV