前言
这是我写的性能优化的第三篇文章,下面是另外两篇文章:
玩安卓必须要掌握的性能优化之内存泄漏
玩安卓必须要掌握的性能优化之APK极限压缩
正文
本篇文章准备详细说一下编码中需要注意的地方,养成良好的编码习惯。
第一点 数据类型
尽量不要使用比需求更占空间的基本数据类型,比如能用 int 就不使用 long,能用 float 就不使用 double,可以减少内存的开销,虽然几乎对程序产生不了太大影响,但是还是要尽量避免。
还有就是自动装箱尽量少用。
第二点 循环
循环尽量使用增强for循环(for each),少用迭代器(iterator)
第三点 数据结构与算法
这一点是最重要的,但也是最难的,其实也不难,关键看能不能坚持下来。每天看一道算法题,半年基本上就能提升非常大的一截。数组、链表、树、栈、图。。。。
还有一点是咱们经常使用的HashMap,写的时候非常自然,直接就写出来了,但是占用内存较大,Android官方为安卓开发者提供了SparseArray(key为整数),当数据量在千级以下可以使用,它的性能虽然不如HashMap但节约内存;千级以上还是使用我们熟悉的HashMap吧。
第四点 枚举优化
曾几何时,因为安卓官方二点几的一句话(图在下方),几乎所有的安卓性能优化中都会有这么一句,但我想说的是,随着硬件的提升,之后的官方文档中早已经找不见这句话了,但不知道为什么2020年了还在流行着这句话,希望大家不要在下面喷我。感谢。
虽然说现在可以用枚举,但是性能优化嘛,本来也就是鸡蛋里挑骨头,咱们可以将枚举替换成常量,并用注解进行个数的限制。下面是代码样例:
public class Constants {
public static final String TYPE_A = "1";
public static final String TYPE_B = "2";
public static final String TYPE_C = "3";
public static final int TYPEDES_A = 1;
public static final int TYPEDES_B = 2;
public static final int TYPEDES_C = 3;
}
//String类型的注解 @StringDef()
@StringDef({Constants.TYPE_A,Constants.TYPE_B,Constants.TYPE_C})
public @interface FieldMata {
}
//int类型的注解
@IntDef({Constants.TYPEDES_A,Constants.TYPEDES_B,Constants.TYPEDES_C})
public @interface TypeDes {
}
代码很简单,使用也不难,下面是使用样例:
//在需要限定的方法内的参数写上先前定义的限定值
private void printType(@FieldMata String type) {
System.out.println(type);
}
private void printType(@TypeDes int des) {
System.out.println(des);
}
public static void main(String[] args) {
DemoTest demoTest = new DemoTest();
demoTest.printType(Constants.TYPE_A);
demoTest.printType(Constants.TYPEDES_A);
}
第五点 static static final的问题
static会由编译器调用clinit方法进行初始化
static final不需要进行初始化工作,打包在dex文件中可以直接调用,并不会在类初始化申请内存
所以基本数据类型的成员,可以全写成static final
第六点 字符串的连接尽量少用加号(+)
这一点大家可能听的耳朵都起茧了,但是不得不说,几次拼接可能无所谓,但是千万不要在循环中还使用加号进行拼接,对内存的消耗真的挺大,尽量还是使用StringBuffer和StringBuilder吧。
第七点 重复申请内存问题
尽量不要在同一个方法多次调用,如递归函数 ,回调函数中new对象,读流直接在循环中new对象等
也不要在onMeause() 、onLayout()、onDraw() 中去刷新UI(requestLayout)
第八点 避免GC回收将来要重用的对象
比如咱们最常用的图片加载框架Glide,它就做的非常好,既实现了LifeCycle,还使用Lru算法,还有三级缓存,这样大大避免了GC回收需要重复使用的图片,可以参考Glide源码的实现。
第九点 尽量使用IntentService,而不是Service
原因很简单,IntentService是一个异步的,会自动停止的服务,很好解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题。
第十点 Activity组件泄漏
- 非业务需要不要把activity的上下文做参数传递,可以传递application的上下文
- 千万不要把和Activity有关联的对象写成static 如private static Button btn; private static Drawable drawable;除了调用比较方便,没有一点好处
- 非静态内部类和匿名内部内会持有activity引用。比如咱们经常写的回调接口,不要使用匿名内部类来实现,尽量使用实现接口的方式来实现,在接收的使用也尽量不要接收Activity,最好使用弱引用(WeakReference),但是别忘了在使用前要进行判空
- 单例模式持有activity引用,这里也是,如果需要Activity尽量使用弱引用
- handler.postDelayed(),如果开启的线程需要传入参数,用弱引接收可解决问题。还有就是handler记得清除removeCallbacksAndMessages(null)
总结
其实上面所说的只是很多编码习惯中比较重要的一些,当然还有很多没有列举出来,如果文中描述有误,欢迎大家留言指正,不胜感激。
来源:oschina
链接:https://my.oschina.net/u/4397965/blog/3234278