• 好的android编码习惯


     上一期分享了android内存优化的一些总结,这一期说说我认为的好的编码习惯,然后下一期会做安卓数据库优化的一些总结,逐渐的会将一些性能优化点总结分享出来,肯定是不够全面的希望不足的地方欢迎指出。

              良好的编码习惯除开编码规范这个不说外,还有很多影响内存,流畅度,耗电量的地方都是需要注意的。我会随时补充进来我遇到的相关的好的编码习惯,但不太容易做到一下就全面。

               1、内存控制

               1.1 已知数量时,对相应的数据结构赋值相应的大小

                new ArrayList(5);

               1.2 勿在循环调用的地方new对象

               比如在adapter中的getView去new OnClickListener,View的onDraw方法new Paint,这些循环多次调用的地方会导致多个对象的产生,不进造成内存增加也会浪费时间。

               1.3 匿名内部类的使用

               上一篇博文提到了原因,匿名内部类会持有外部引用,所以这里改成静态内部类的,同时使用弱引用的方式。

                1.4 enum的使用

               2、节省时间

               2.1 用变量替代计算

               不论是for循环中,还是自己实现一些代码通过用一个变量记录值,比循环计算得出来的值更加节省时间。比如

              for(int i =0;i < array.length;i++) 可以替换成

              final int size = array.length;

             for(int i = 0; i< size;i++),这样可以减少循环过程中的计算

            不过据说现在foreach的方式是最快的,有兴趣的朋友可以测试下。

              2.2 字符串的拼接使用StringBuilder或者StringBuffer

            比如"select * from " + Tables.table_name+" where id = "+sid+" limit 1";字符串的拼接不光是时间损耗,内存也会损耗。如果一个字符串后面跟着一个+号,再后面是任何的类型表达式:

             string_exp + any_exp

    Java编译器会把它变成:

             new StringBuilder().append( string_exp ).append( any_exp ).toString()

    如果表达式里有多个+号的话,后面相应也会多多几个StringBuilder.append的调用,最后才是toString方法。

    而StringBuilder(String)这个构造方法会分配一块16个字符的内存缓冲区。因此,如果后面拼接的字符不超过16的话,StringBuilder不需要再重新分配内存,不过如果超过16个字符的话StringBuilder会扩充自己的缓冲区。最后调用toString方法的时候,会拷贝StringBuilder里面的缓冲区,新生成一个String对象返回。

              关于字符串拼接的优化除了StringBuilder或者buffer外还可以做的更好一点,这也是一次面试得到的经验,可以下一次分享给大家。

             2.3 注意强制类型转换

            使用Integer.parseInt()而不是(int)Integer.valueOf()然后去做对比,减少类型强制转换的时间

            2.4 对常量使用Static Final修饰符,

            2.5 避免内部getters和setters(有争议)

            性能上直接访问变量更加有效率,但是软件工程上就对外暴露了同时也不容易面向扩展了,所以这里只是提出来,并不一定要遵守。

             2.6 在私有内部类中,考虑用包访问权限替代私有访问权限

             访问外部内的私有方法,会让虚拟机生成黏合方法,也就是getters和setters的方法从而降低了读取的性能。

              2.7 线程的优先级设定

              首先不要同时使用过多的线程,一来难以管理,二来也会耗费cpu资源,导致影响UI线程,所以在使用线程时,在执行优先级不高的情况下,指定线程最低优先级或者后台优先级等,保证UI线程的优先级,比如:

            new Thread(new Runnable() {

            @Override

                    public void run() {

                         Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);

                    }

               }).start();

              2.8 使用System.arraycopy ()代替通过来循环复制数组

              2.9 避免循环内部有过多依赖和跳转,使cpu能流水起来

              比如:

             for(int i =0; i < N; i++){

                   if(i <100) 

                         a[i] +=5;

                   else if(i <200) 

                        a[i] +=10;

                    else

                         a[i] +=20;

                     }

                    改成三个循环

                    for(int i = 0; i < 100; i++)

                  {

                            a[i] += 5;

                    }

                      for(int i = 100; i < 200; i++)

                      {

                               a[i] += 10;

                       }

                       for(int i = 200; i < N; i++)

                       {

                                a[i] += 20;

                         }

               3、对应的生命周期

              3.1  set(listener)对于set(null)

              3.2  add对应remove

              3.3 open对应close

               4、屏幕网络CPU耗电量杀手

               4.1 选择合适的wakelock模式

              PARTIAL_WAKE_LOCK:保持CPU运转,屏幕和键盘灯有可能是关闭的。

              SCREEN_DIM_WAKE_LOCK:保持CPU运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯

               SCREEN_BRIGHT_WAKE_LOCK:保持CPU运转,保持屏幕高亮显示,允许关闭键盘灯

               FULL_WAKE_LOCK:保持CPU运转,保持屏幕高亮显示,键盘灯也保持亮度

               ACQUIRE_CAUSES_WAKEUP:不会唤醒设备,强制屏幕马上高亮显示,键盘灯开启。有一个例外,如果有notification弹出的话,会唤醒设备。

               ON_AFTER_RELEASE:WakeLock被释放后,维持屏幕亮度一小段时间,减少WakeLock循环时的闪烁情况

               用完必须要记得释放。

               4.2 选择合适的alarmmanage模式

              AlarmManager会维持一个cpu的wakelock。这样能保证电话休眠时,也能处理alarm的广播,有4种Alarm类型:

              1)RTC_WAKEUP

              在指定的时刻(设置Alarm的时候),唤醒设备来触发Intent。

              2)RTC

              在一个显式的时间触发Intent,但不唤醒设备。

              3)ELAPSED_REALTIME

              从设备启动后,如果流逝的时间达到总时间,那么触发Intent,但不唤醒设备。流逝的时间包括设备睡眠的任何时间。注意一点的是,时间流逝的计算点是自从它最后一次启动算起。

              4)ELAPSED_REALTIME_WAKEUP

              从设备启动后,达到流逝的总时间后,如果需要将唤醒设备并触发Intent。

             4.3 慎用轮询 

             这玩意耗电很大,当然很多时候可能是配合上面的AlarmManager使用,可以在不同的界面或者功能,定义不同的轮询时间来做优化等。

            5、IO优化

            5.1 使用缓存区

            通过缓存减少磁盘读取次数

            5.2 缓冲块的IO要比缓冲流IO要快

             6、功能范围

            6.1 合理的synchronized范围

            6.2 合理的try/catch范围

            try/catch住爆出异常的区域,而不是一个大的函数。

  • 相关阅读:
    Oracle函数如何把符串装换为小写的格式
    Oralce中的synonym同义词
    JS中getYear()的兼容问题
    How to do SSH Tunneling (Port Forwarding)
    所谓深度链接(Deep linking)
    upload size of asp.net
    发一个自动刷网站PV流量的小工具
    解决Visual Studio 2008 下,打开.dbml(LINQ) 文件时,提示"The operation could not be completed." 的问题。
    在资源管理器中使鼠标右键增加一个命令,运行cmd,同时使得当前路径为资源管理器当前的目录
    使用SQL语句获取Sql Server数据库的版本
  • 原文地址:https://www.cnblogs.com/dongweiq/p/4372089.html
Copyright © 2020-2023  润新知