性能优化

一个上线的App软件,首先要讲究良好的用户体验,如果一款软件卡顿现象严重,不流畅,经常崩溃,那么将给用户带来极不良好的体验,从而损失用户。 下面来介绍一下性能优化,大家可以广提建议。

一.Android性能优化主要包括布局优化、绘制优化、内存泄露优化、响应速度优化、ListView优化、Bitmap优化、线程优化以及一些优化建议.

绘制优化(onDraw)

主要是避免执行大量的操作.

  1. 不要创建新的局部对象,因为onDraw可能会被频繁调用,会在一瞬间产生大量的临时对象,会导致占用过多内存,系统更加频繁的gc,降低执行效率
  2. 不要做耗时的任务

内存泄露优化

其实内存泄露有很多种情况,但是书中列举的比较少

  1. 静态变量导致的内存泄露(比如静态的context,静态的view)
  2. 单例模式持有Activity
  3. 属性动画(repeatCount为无限模式)

ListView和Bitmap优化

ListView使用viewholder模式,Bitmap在12章有讲,这里不重复.

线程优化

主要是采用线程池(11章有讲)

  1. 避免存在大量的Thread
  2. 重用Thread,避免线程创建和销毁所带来的开销
  3. 线程池还能控制最大并发数,避免大量线程因互相抢占系统资源从而导致阻塞

布局优化

  1. 减少布局文件的层级(测量/布局/绘制的时间减少):可以使用RelativeLayout来减少嵌套,从而达到减少层级的目的,另外在相同层级的情况下使用LinearLayout(相比于RelativeLayout更高效)
  2. 使用include标签复用,merge标签降低层级,ViewStub来实现懒加载,另外补充一个Space可以用来占位

当然,还有很多优化的方法。我这里只介绍一些经常用到的。

其他的一些性能优化建议

  1. 避免创建过多的对象
  2. 不要过多使用枚举(枚举占用的内存空间要比整型的大)
  3. 常量使用 static final来修饰
  4. 使用一些Android特有的数据结构,比如SparseArrayPair等,它们都具有更好的性能(注:减少了自动装箱和拆箱的消耗)
  5. 适当使用软引用和弱引用
  6. 尽量采用静态内部类(不会持有外部类的实例

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

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

2.合理使用static成员 

主要有三点需要掌握: 
如果一个方法不需要操作运行时的动态变量和方法,那么可以将方法设置为static的。 
常量字段要声明为“static final”,因为这样常量会被存放在dex文件的静态字段初始化器中被直接访问,否则在运行时需要通过编译时自动生成的一些函数来初始化。此规则只对基本类型和String类型有效。 
不要将视图控件声明为static,因为View对象会引用Activity对象,当Activity退出时其对象本身无法被销毁,会造成内存溢出。 
3. 避免内部的Getters/Setters 
面向对象设计中,字段访问使用Getters/Setters通常是一个好的原则,但是在Android开发中限于硬件条件,除非字段需要被公开访问,否则如果只是有限范围内的内部访问(例如包内访问)则不建议使用Getters/Setters。在开启JIT时,直接访问的速度比间接访问要快7倍。 
4. 使用增强for循环 
优先使用增强for循环通常情况下会获得更高的效率;除了一种情况,即对ArrayList进行遍历时,使用普通的for循环效率要更高。 
5. 使用public代替private以便私有内部类高效访问外部类成员 
   私有内部类的方法访问外部类的私有成员变量和方法,在语法上是正确的,但是虚拟机在运行时并不是直接访问的,而是在编译时会在外部类中自动生成一些包级别的静态方法,执行时内部类会调用这些静态方法来访问外部类的私有成员。这样的话就多了一层方法调用,性能有所损耗。 
一种解决这个问题的方法就是将外部类的私有成员改为包级别的,这样内部类就可以直接访问,当然前提是设计上可接受。 
6.合理使用浮点类型 
   在Android设备中浮点型大概比整型数据处理速度慢两倍,所以如果整型可以解决的问题就不要用浮点型。 
另外,一些处理器有硬件乘法但是没有除法,这种情况下除法和取模运算是用软件实现的。为了提高效率,在写运算式时可以考虑将一些除法操作直接改写为乘法实现,例如将“x / 2”改写为“x * 0.5”。 
7.采用<merge>优化布局层数。 采用<include>来共享布局。 
8.延时加载View. 采用ViewStub 避免一些不经常的视图长期被引用,占用内存. 
9.移除Activity默认背景,提升activity加载速度。 
   如果确信在Activity中使用不透明的背景,那么可以移除Activity的默认背景。 
在代码中:getWindow().setBackgroundDrawable(null); 
也可以在styles样式文件中设置并在Manifest文件中配置

 <style name="MyStyle" parent="AppTheme">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@null</item>  
 </style>

 

10.cursor 的使用。 
要注意管理好cursor,不要每次打开关闭cursor.因为打开关闭Cursor非常耗时。 
不再使用的cursor要记得关闭(一般在finally语句块执行)。 
有一种情况下,我们不能直接将Cursor关闭掉,这就是在CursorAdapter中应用的情况,但是注意,CursorAdapter在Acivity结束时并没有自动的将Cursor关闭掉,因此,你需要在onDestroy函数中,手动关闭。

protected void onDestroy() { 
      if (mAdapter != null && mAdapter.getCurosr() != null) { 
          mAdapter.getCursor().close(); 
      } 
      super.onDestroy(); 
    }

 

 

 

11.广播BroadCast动态注册时,记得要在调用者生命周期结束时unregisterReceiver,防止内存泄漏。 
12.针对ListView的性能优化 
item尽可能的减少使用的控件和布局的层次;背景色与cacheColorHint设置相同颜色;ListView中item的布局至关重要,必须尽可能的减少使用的控件,布局。RelativeLayout是绝对的利器,通过它可以减少布局的层次。同时要尽可能的复用控件,这样可以减少ListView的内存使用,减少滑动时GC次数。ListView的背景色与cacheColorHint设置相同颜色,可以提高滑动时的渲染性能。ListView中getView是性能是关键,这里要尽可能的优化。getView方法中要重用view;getView方法中不能做复杂的逻辑计算,特别是数据库操作,否则会严重影响滑动时的性能;ListView数据项较多时考虑分页加载。 
13.注意使用线程的同步机制(synchronized),防止多个线程同时访问一个对象时发生异常。 
14.合理使用StringBuffer,StringBuilder,String 
在简单的字符串拼接中,String的效率是最高的,例如String s = “hello” + “world”; 
但大家这里要注意的是,如果你的字符串是来自另外的String对象的话,速度就没那么快了,例如: 
    String str2 = “This is”; 
    String str3 = “ a ”; 
    String str4 = “ test”; 
    String str1 = str2 +str3 + str4; 
这里就要求使用StringBuilder了 
在单线程中,StringBuilder的性能要比StringBuffer高。多线程为了线程安全需要采用StringBuffer,因为它是同步的。常规下一般用StringBuilder。 
15. 尽量使用局部变量 
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。另外,依赖于具体的编译器/JVM,局部变量还可能得到进一步优化。 
16.I/O流操作记得及时关闭流对象。 
17.使用IntentService代替Service 
IntentService和Service都是一个服务,区别在于IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent(在onHandleIntent方法中),对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。 
18.使用Application Context代替Activity中的Context 
不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的 
对于生命周期长的对象,可以使用Application Context 
不要把Context对象设置为静态。 
19.集合中的对象要及时清理 
 我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。 
20.Bitmap的使用 
较大的Bitmap注意压缩后再使用,加载高清大图可以考虑BitmapRegionDecoder的使用, 
不再使用的Bitmap注意及时recycle().

21.巧妙的运用软引用(SoftRefrence) 
 有些时候,我们使用Bitmap后没有保留对它的引用,因此就无法调用Recycle函数。这时候巧妙的运用软引用,可以使Bitmap在内存快不足时得到有效的释放。有关Java引用机制的介绍可以看我的另一篇博客:http://blog.csdn.net/gs12software/article/details/51051813 
22.尽量不要使用整张的大图作为资源文件,尽量使用9path图片 
应用图标优先放在mipmap目录下(AndroidStudio环境),其他资源图,.9图应该放在drawable-xxxx下,需要复制到手机sd卡上使用的应放在asset目录 
23.了解并使用库函数 
Java标准库和Android Framework中包含了大量高效且健壮的库函数,很多函数还采用了native实现,通常情况下比我们用Java实现同样功能的代码的效率要高很多。所以善于使用系统库函数可以节省开发时间,并且也不容易出错。 
24.关于WebView 
在Activity或者Fragment销毁时记得把WebView也销毁

@Override
    protected void onDestroy() {
        if (webView!= null) {
            webView.destroy();
            webView= null;
        }
        super.onDestroy();
    }

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值