加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_阳江站长网 (https://www.0662zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 移动互联 > 应用 > 正文

干货分享之也谈App性能优化

发布时间:2022-12-01 12:55:44 所属栏目:应用 来源:
导读:  如果自己造轮子的话,还需要我们花时间去验证去适应我们的业务需求,但好处是我们可以自己去扩展可把控,不过这很考量开发者的素质。

  数据解析

  实际开发当中服务端的返回数据格式无非就两种:
  如果自己造轮子的话,还需要我们花时间去验证去适应我们的业务需求,但好处是我们可以自己去扩展可把控,不过这很考量开发者的素质。
 
  数据解析
 
  实际开发当中服务端的返回数据格式无非就两种:
 
  - JSON
 
  - XML
 
  这两种格式数据格式各有优劣,从可读性来看,xml略微好一点,不过JSON也有规范的标签,从解析难度和速度来看,大家都比较倾向使用JSON,目前JSON也是主流的数据格式。
 
  在Android中均可以使用优秀的解析库来加快我们的解析速度,XML中有dom4j,JSON有Jackson、Gson,我们通过这些库实现我们更快的完成数据解析,提高我们的开发效率。
 
  数据存储
 
  上一节讲的是数据解析,我们解析完后的数据,可能就需要将数据存储在某个地方,Android的五种存储方式:
 
  - Content Provider(主要用来向其他应用程序共享数据)
 
  - SQLite(存储数据到数据库中)
 
  - File(本地文件保存)
 
  - SharedPreference(主要用来保存简单的配置信息)
 
  - 网络存储(WebService返回的数据或是解析HTTP协议实现网络数据交互)
 
  为了提高应用程序的响应时间,数据缓存是一个比较好的方式,我们可以预处理服务器返回的数据,对数据进行缓存刷新。
 
  优化点:
 
  - 异步请求网络数据
 
  - 预处理服务器返回数据
 
  - 异步进行数据存储操作
 
  - 数据缓存刷新
 
  - Timeout超时重试
 
  - 在主线程中操作UI
 
  界面卡顿
 
  ANR表示”应用程序无响应”,这个是需要我们避免发生的事情,出现这个异常的原因:
 
  - 主线程 (“事件处理线程” / “UI线程”) 在5秒内没有响应输入事件
 
  - BroadcastReceiver在10秒内没有执行完毕
 
  导致ANR的原因有很多,一般情况就是在UI线程做了耗时的操作,例如”网络请求”、数据库操作。
 
  那么如何避免?
 
  - UI线程只做界面刷新,不做任何耗时操作,耗时操作放在子线程来做
 
  - 可以使用Thread+handle或者AsyncTask来进行逻辑处理
 
  耗内存
 
  每部手机的内存有限,我们这里所说的内存指的是手机的RAM,它是Ramdom Access Memory的缩写,我们应用程序的需要随机读写的数据就存在RAM中,Android手机之所以会比较耗内存,这跟Android后台的处理有关,我们知道Android应用是使用Java开发的,运行Java需要有虚拟机,说明每开启一个应用都会创建一个虚拟机,而这是需要内存的,所以我们开的应用越多,后台进程越多,内存都分配出去了,才导致内存消耗的严重。
 
  其实这个问题我们是没得破的,只要内存不够,我们的应用还是会卡。我们开发的应用依赖与系统给我们分配的堆内存,一般上限在16M~48M,但我们可以通过在AndroidManifest设置Application属性largeHeap=“true”来申请更多的堆内存。
 
  通过以下代码获取可用堆内存限制:
 
  mActivityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
 
  mMaxMemory = mActivityManager.getMemoryClass();
 
  内存泄露
 
  内存泄露这个问题已经被说烂了,大家都知道有内存泄露这个问题存在,但为什么会发生内存泄露?
 
  这里的内存泄露并不是真正意思上的泄露,而是因为内存不足不能进行GC操作,从而导致占用内存过大,抛出out of memory异常,而被系统Kill掉。
 
  JVM回收机制
 
  是时候讲讲JVM的回收机制了,看下图:
 
  聚合物材料结构、性能、应用_聚合物材料:结构、性能、应用_应用性能管理
 
  JVM对Java对象分了三个代进行管理,分别为年轻代、年老代、永久代。
 
  年轻代(Young Generation):绝大多数的Java对象会在年轻代被分配,也会在年轻代被回收。
 
  年老代(Old Generation):在年轻代长期存在没有被回收的Java对象会转移到年老代,这个堆空间通常会被比年轻代的堆空间要大。
 
  永久代:存放VM和Java类的元数据,以及interned字符串和类的静态变量。
 
  这里涉及到JVM的相关知识,这里不继续深入探讨。
 
  但我们应该可以知道垃圾回收器的作用:
 
  - 分配内存
 
  - 保证所有正在被引用的对象还存在于内存中
 
  - 回收执行代码已经不再引用的对象所占的内存
 
  对象引用
 
  Java的引用类型可以分为以下几种:
 
  - 强引用(Strong Ref):强可达,去掉强可达,才会被回收。
 
  - 软引用(Soft Ref):内存够用,就保持,内存吃紧,则回收,主要用来做缓存。
 
  - 弱引用(Weak Ref):比Soft Ref弱,即使内存不吃紧也会被回收。
 
  - 虚引用(Phantom Ref):不会在内存保持任何对象。
 
  一图胜千言:
 
  应用性能管理_聚合物材料结构、性能、应用_聚合物材料:结构、性能、应用
 
  利用Strong Ref,存储大量数据,直到heap撑破,利用inter strings(或者class loader加载大量的类)把perm gen撑破,然后就是内存泄露了。
 
  如何优化?
 
  前面讲了一些背景知识,对我们理解内存优化有一定的帮助,下面就简单说一下我们优化的方向:
 
  - 布局优化
 
  - 内存优化
 
  布局优化
 
  大家可以拿出你们的Android机
 
  开发者工具-Profile GPU Rendering-选择在屏幕上显示条形图
 
  -蓝色代表测量绘制Display List的时间
 
  -红色代表OpenGL渲染Display List所需要的时间
 
  -黄色代表CPU等待GPU处理的时间
 
  -中间绿色横线代表VSYNC时间16ms,尽量将所有条形图控制在这条绿线下
 
  为什么是16ms?
 
  Android 通知界面渲染和重绘的时间要在16ms内完成,如果超过16ms,就会导致丢帧,也就是我们常说的卡顿。
 
  优化点:
 
  - 避免OverDraw
 
  - 优化布局层级
 
  - 避免过多无用嵌套
 
  - 使用标签重用layout
 
  - 使用延迟加载
 
  - Hierarchy View进行层级分析
 
  具体的使用方法,这里不介绍了,不懂就百度。
 
  内存优化
 
  内存优化的点有很多,这里我主要分为两大块:
 
  - Bitmap优化
 
  - 代码优化
 
  Bitmap优化
 
  1.使用适当分辨率和大小的图片
 
  2.及时回收内存(bitmap.recycle())
 
  3.使用图片缓存(LruCache和DiskLruCache)
 
  第一点,就是按需显示,比如列表中的图片,你可以显示缩略图,详情页,你就可以加载相应的分辨率的图片,这样可以减少内存消耗,一般可以要求服务端提供多种分辨率的图片。
 
  第二点,Bitmap是很耗内存,尤其是加载比较大的bitmap,可以想到的优化方案就是使用记得回收,对Bitmap进行压缩,使用BitmapFactory.Options设置inSampleSize就可以缩小图片。
 
  第三点,图像缓存,这个可以利用成熟的图片加载框架,比如Universal-ImageLoader、Fresco、Picasso,这些框架都对图片进行了很好的优化,大家可以对比一下,选择使用即可。
 
  代码优化
 
  关于代码这个就有的说了,任何能改进我们程序的优化点都能写在这里,这里没办法把所有优化的点列在这里,只提供相关的参考,剩下的就好各位经验总结和积累了。
 
  优化点:
 
  - 对常量使用static修饰符
 
  - 使用静态方法
 
  - 减少不必要的成员变量
 
  - 尽量不要使用枚举,少用迭代器
 
  - 对Cursor、Receiver、Sensor、File等对象,要注意它们的创建、回收与注册、反注册
 
  - 避免大量使用注解、反射
 
  - 使用RenderScript、OpenGL来进行复杂的绘图操作
 
  - 使用SurfaceView来替代View进行大量、频繁的绘图操作
 
  - 尽量使用视图缓存,而不是每次都执行inflate()方法解析视图
 
  注:这里引用了Android群英传的相关优化点
 
  创建新的对象都需要额外的内存空间,要尽量减少创建新的对象。
 
  将类、变量、方法等等的可见性修改为最小。
 
  针对字符串的拼接,使用StringBuffer替代String。
 
  不要在循环当中声明临时变量,不要在循环中捕获异常。
 
  如果对于线程安全没有要求,尽量使用线程不安全的集合对象。
 
  使用集合对象,如果事先知道其大小,则可以在构造方法中设置初始大小。
 
  文件读取操作需要使用缓存类,及时关闭文件。
 
  慎用异常,使用异常会导致性能降低。
 
  如果程序会频繁创建线程,则可以考虑使用线程池。
 
  以上都是些经验总结,大致都相差无几,朋友们在做代码优化的时候,可以根据这些优化点应用性能管理,有针对性去重构代码,其实最重要还是代码的可读性,结构清晰。
 
  性能优化工具
 
  Memory Monitor - 内存监视工具
 
  TraceView
 
  MAT
 
  Android开发者对与以上几个性能调优的工具一定不陌生,这里我也不再写那么多废话了。
 
  最后
 
  写这篇文章的出发点也是对Android性能优化有个比较清楚的认识,任何事情都不可能一蹴而就,需要循循渐进,对一个初学者你谈优化很不现实,我们先把基本的做好,再去考虑相应的优化。
 

(编辑:应用网_阳江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!