天天看点

Android高性能编码四:代码优化

TPS(Transaction Per Second)

TPS为每秒处理的事务数,是系统吞吐量的指标,在搜索系统中也用QPS(Query Per Second)衡量。TPS一般与响应时间反相关。

通常所说的性能问题就是指响应时间过长、系统吞吐量过低。

Android高性能编码一:多线程并发或分布式提高TPS

Android高性能编码二:利用缓存提高TPS

Android高性能编码三:数据结构和算法优化

Android高性能编码四:代码优化

代码的细节有时也会很影响性能,在执行次数不是很频繁时并不明显,在核心的频繁的代码一定要注意细节。

1.选择ArrayList最佳的遍历方式

//方法1
        Iterator it1 = list.iterator();
        while(it1.hasNext()){
            System.out.println(it1.next());
        }

        //方法2
        for(Iterator it2 = list.iterator();it2.hasNext();){
             System.out.println(it2.next());
        }

        //方法3
        for(String tmp:list){
            System.out.println(tmp);
        }

        //方法4
        int size = list.size();
        for(int i = 0;i < size; i ++){
            System.out.println(list.get(i));
        }

        //逆序
        for(int i = list.size();i >=0; i --){
            System.out.println(list.get(i));
        }
           

一般第三种和第四种遍历的耗时是最低的,list的size提前取出,否则每次循环的时候都要取一次。

第四种的变种逆序可以对list的元素进行操作,不会报ConcurrentModificationException的Exception。

2.static常量加上final

public class Test {

    private  final static int i1 = 0;
    private  final static int i2 = 0;
    private  final static int i3 = 0;
    private  final static int i4 = 0;
    private  final static int i5 = 0;
    private  final static int i6 = 0;
    private  final static int i7 = 0;
    private  final static int i8 = 0;
    private  final static int i9 = 0;
    private  final static int i10  = 0;
    private  final static int i11  = 0;
    private  final static int i12 = 0;
    private  final static int i13 = 0;
    private  final static int i14 = 0;
    private  final static int i15 = 0;
    private  final static int i16 = 0;
    private  final static int i17 = 0;
    private  final static int i18 = 0;
    private  final static int i19 = 0;
    private  final static int i20 = 0;
    private  final static String str1 = "Test1";
    private  final static String str2 = "Test2";
    private  final static String str3 = "Test3";
    private  final static String str4 = "Test4";
    private  final static String str5 = "Test5";
    private  final static String str6 = "Test6";
    private  final static String str7 = "Test7";
    private  final static String str8 = "Test8";
    private  final static String str9 = "Test9";
    private  final static String str10 = "Test10";


    public Test(){

    }


    public void count(){

        int sum = i1+i2+i3+i4+i5+i6+i7+i8+i9+i10+i11+i12+i13+i14+i15+i16+i17+i18+i19+i20;

//        Log.i("Test", "sum:"+sum);

    }

    public void connect(){

        StringBuilder sb = new StringBuilder();
        sb.append(str1);
        sb.append(str2);
        sb.append(str3);
        sb.append(str4);
        sb.append(str5);
        sb.append(str6);
        sb.append(str7);
        sb.append(str8);
        sb.append(str9);
        sb.append(str10);

//        Log.i("Test", "sb:"+sb.toString());
    }
}
        long start = System.currentTimeMillis();
        Log.d("Test", "startTime:"+start);

        for(int i = 0; i < 10000; i++) {
            Test test = new Test();
            test.count();
            test.connect();
        }
        Log.d("Test", "cost time:"+(System.currentTimeMillis()-start));
           

测试类

04-25 10:50:58.884 17229-17229/com.js.test2 D/Test: startTime:1493088658884
04-25 10:50:58.907 17229-17229/com.js.test2 D/Test: cost time:23
           

不加final执行耗时23毫秒

04-25 10:52:45.543 19973-19973/? D/Test: startTime:1493088765543
04-25 10:52:45.560 19973-19973/? D/Test: cost time:17
           

加final执行耗时17毫秒

static常量不加final,类加载时会在cinit方法中,为int和String变量赋值并建立字符串映射。当你加上final之后,变量会在编译时就初始化了,不必再建立字符串映射和int赋值。

3.减少布局层次

推荐使用布局RelativeLayout,虽然在写布局时会麻烦一些,但是可以有效的减少布局层次,从而减少OverDraw,减少绘制的次数,绘制是很耗费性能的。一般OverDraw为红色的区域不要超过屏幕的4分之一。

4.谨慎使用static静态变量

a.static静态变量引用有生命周期的组件的时候,比如activity、context、以及context有关的资源时,会造成这些组件不能释放内存,就造成了内存泄漏。

b.不用静态变量保存数据

在activity中使用静态变量保存数据,在activity切换时,数据有可能被清除掉。建议使用Application或者Application的子类来保存数据。

5.及时释放不工作的线程

一般单独写线程时,都能在不使用时设置为null。问题都是出在一些比较常用的封装的线程组件,比如HanderThread、线程池等。

HandlerThread start的时候会自动创建线程池并等待,如果不在退出的时候及时的释放这些线程,它们会等在那里,所以HandlerThread不使用时,要及时调用quit或quitSafely。

6.灵活使用getter和setter方法

为了封装解耦,理论上bean的所有数据都要采用getter和setter方法来访问,但是,public 直接调用变量显然要比getter方法高效,一些调用频繁的变量可以考虑直接public调用,或者直接采用内部类设计,这样兼顾解耦和性能。

7.减少浮点型的使用

Android设备使用浮点型速度比整形慢很多,而且浮点型与浮点型的运算有时并不可靠,比如1000.0f x 1000.f的结果并不等于1000000,而是等于999999.4565465,基本上商业运算采用BigDecimal更加准确。

继续阅读