安卓代码优化(3)
2015-11-06 16:54
281 查看
1、避免创建短命的临时对象。
减少对象的创建就能减少垃圾收集,进而减少对用户体验的影响。
案例:
(1)截取一段字符串时,尽量使用substring函数取得原始数据的一个子串,而不是为子串另外建立一份拷贝。
(2)多维数组分成多个一维数组
(3)int数组比Integer数组好,这也概括了一个基本事实,两个平行的int数组比 (int,int)对象数组性能要好很多
2、静态方法:
如果不需要访问某对象的字段,将方法设置为静态,调用会加速15%到20%。
3、 避免内部Getters/Setters
在公共接口中使用Getters和Setters是有道理的,
但在一个字段经常被访问的类中宜采用直接访问。
无JIT时,直接字段访问大约比调用getter访问快3倍。有JIT(编译器)时(直接访问字段开销等同于局部变量访问),要快7倍。
4、将成员缓存到本地
(1)访问成员变量比访问本地变量慢得多
一般代码:直接访问成员变量
//////改成访问本地变量:更快
(2)永远不要在for的第二个条件中调用任何方法:
(3)、同样如果你要多次访问一个变量,也最好先为它建立一个本地变量(方法的参数和本地变量一样)
一般的代码:
//////分析:
mScrollBar在方法中使用了四次,可以将他转换为本地变量!
5、 对常量使用static final修饰符
案例:
static int intVal = 42;
在编译过程中:
必以其会生成一个叫做clinit的初始化类的方法,当类第一次被使用的时候这个方法会被执行。方法会将42赋给intVal;
/////改进:加上final:
—->
类不再需要clinit方法,因为在成员变量初始化的时候,会将常量直接保存到类文件中;
//////////分析:
将一个方法或类声明为final不会带来性能的提升,
但是会帮助编译器优化代码。
举例说,如果编译器知道一个getter方法不会被重载,那么编译器会对其采用内联调用。
5、改进的for循环语 法和迭代器具有相同的效率
在其他集合类中:
迭代器让接口调用 hasNext()和next()方法。在ArrayList中,手写的计数循环迭代要快3倍(无论有没有JIT)
for展示集中访问数组:
6、 避免使用浮点数
7、了解并使用类库
选择Library中的代码而非自己重写,除了通常的那些原因外,
考虑到系统空闲时会用汇编代码调用来替代library方法;
涉及到的场景:(c、c++实现的)
(1)String.indexOf(),String.lastIndexOf()等特殊实现的方法、System.arraycopy比循环快多了!
(2) android.text.format包下的Formatter类,
提供了IP地址转换、文件大小转换等方法;
DateFormat类,提供了各种时间转换,都是非常高效的方法
(3)、系统的TextUtils类
字符串处理Android为我们提供了一个简单实用的TextUtils类
(4)、高性能MemoryFile类
实现高性能的文件读写操作
/////分析:
对于I/O需要频繁操作的,主要是和外部存储相关的I/O操作,MemoryFile通过将 NAND或SD卡上的文件,分段映射到内存中进行修改处理
8、合理利用本地方法
当你分配本地资源时 (本地堆上的内存,文件说明符等),往往很难实时的回收这些资源。
9、复杂算法尽量用C完成
复杂算法尽量用C或者C++完成,然后用JNI调用;
10、减少不必要的全局变量
尽量避免static成员变量引用资源耗费过多的实例,比如Context。
Android提供了很健全的消息传递机制(Intent)和任务模型(Handler),可以通过传递或事件的方式,防止一些不必要的全局变量。
11、资源的回收,不用过多指望gc:
Java的gc使用的是一个有向图,判断一个对象是否有效看的是其他的对象能到达这个对象的顶点
显示让系统回收:
12、了解Java四种引用方式
强引用、软引用、弱引用和虚引用
13、使用实体类比接口好
//接口
Map map1 = new HashMap();
//接口
HashMap map2 = new HashMap();
14、避免使用枚举:
枚举变量非常方便,但不幸的是它会牺牲执行的速度和并大幅增加文件体积
/////改进:
使用ordinal()方法获取枚举变量的整数值会更好一些:
15、在私有内部内中,考虑用包访问权限替代私有访问权限
//////分析:
可以通过声明被内部类访问的字段和成员为包访问权限,而非私有。但这也意味着这些字段会被其他处于同一个包中的类访问,因此在公共API中不宜采用。
16、适量使用缓存:
17、关闭资源对象:
对SQLiteOpenHelper,SQLiteDatabase,Cursor,文件,I/O操作等都应该记得显示关闭。
减少对象的创建就能减少垃圾收集,进而减少对用户体验的影响。
案例:
(1)截取一段字符串时,尽量使用substring函数取得原始数据的一个子串,而不是为子串另外建立一份拷贝。
(2)多维数组分成多个一维数组
(3)int数组比Integer数组好,这也概括了一个基本事实,两个平行的int数组比 (int,int)对象数组性能要好很多
2、静态方法:
如果不需要访问某对象的字段,将方法设置为静态,调用会加速15%到20%。
3、 避免内部Getters/Setters
在公共接口中使用Getters和Setters是有道理的,
但在一个字段经常被访问的类中宜采用直接访问。
无JIT时,直接字段访问大约比调用getter访问快3倍。有JIT(编译器)时(直接访问字段开销等同于局部变量访问),要快7倍。
4、将成员缓存到本地
(1)访问成员变量比访问本地变量慢得多
一般代码:直接访问成员变量
for(int i =0; i <this.mCount; i++) { dumpItem(this.mItems); }
//////改成访问本地变量:更快
//////转为本地变量: int count = this.mCount; Item[] items = this.mItems; for(int i =0; i < count; i++) { dumpItems(items); }
(2)永远不要在for的第二个条件中调用任何方法:
for(int i =0; i < this.getCount(); i++) {}
(3)、同样如果你要多次访问一个变量,也最好先为它建立一个本地变量(方法的参数和本地变量一样)
一般的代码:
protected void drawHorizontalScrollBar(Canvas canvas, int width, int height) { if(isHorizontalScrollBarEnabled()) { intsize = mScrollBar.getSize(false); if(size <=0) { size = mScrollBarSize; } mScrollBar.setBounds(0, height - size, width, height); mScrollBar.setParams(computeHorizontalScrollRange(), computeHorizontalScrollOffset(), computeHorizontalScrollExtent(),false); mScrollBar.draw(canvas); } }
//////分析:
mScrollBar在方法中使用了四次,可以将他转换为本地变量!
5、 对常量使用static final修饰符
案例:
static int intVal = 42;
在编译过程中:
必以其会生成一个叫做clinit的初始化类的方法,当类第一次被使用的时候这个方法会被执行。方法会将42赋给intVal;
/////改进:加上final:
—->
类不再需要clinit方法,因为在成员变量初始化的时候,会将常量直接保存到类文件中;
//////////分析:
将一个方法或类声明为final不会带来性能的提升,
但是会帮助编译器优化代码。
举例说,如果编译器知道一个getter方法不会被重载,那么编译器会对其采用内联调用。
5、改进的for循环语 法和迭代器具有相同的效率
在其他集合类中:
迭代器让接口调用 hasNext()和next()方法。在ArrayList中,手写的计数循环迭代要快3倍(无论有没有JIT)
for展示集中访问数组:
static class Foo { int mSplat; } Foo[] mArray = ... //每次循环都会访问两次静态成员变量,取得一次数组的长度。 public void zero() { int sum = 0; for (int i = 0; i < mArray.length; ++i) { sum += mArray[i].mSplat; } } //将所有成员变量存储到本地变量 public void one() { int sum = 0; Foo[] localArray = mArray; int len = localArray.length; for (int i = 0; i < len; ++i) { sum += localArray[i].mSplat; } } //每次执行时会给a进行赋值 public void two() { int sum = 0; for (Foo a : mArray) { sum += a.mSplat; } } }
6、 避免使用浮点数
7、了解并使用类库
选择Library中的代码而非自己重写,除了通常的那些原因外,
考虑到系统空闲时会用汇编代码调用来替代library方法;
涉及到的场景:(c、c++实现的)
(1)String.indexOf(),String.lastIndexOf()等特殊实现的方法、System.arraycopy比循环快多了!
(2) android.text.format包下的Formatter类,
提供了IP地址转换、文件大小转换等方法;
DateFormat类,提供了各种时间转换,都是非常高效的方法
(3)、系统的TextUtils类
字符串处理Android为我们提供了一个简单实用的TextUtils类
(4)、高性能MemoryFile类
实现高性能的文件读写操作
/////分析:
对于I/O需要频繁操作的,主要是和外部存储相关的I/O操作,MemoryFile通过将 NAND或SD卡上的文件,分段映射到内存中进行修改处理
8、合理利用本地方法
当你分配本地资源时 (本地堆上的内存,文件说明符等),往往很难实时的回收这些资源。
9、复杂算法尽量用C完成
复杂算法尽量用C或者C++完成,然后用JNI调用;
10、减少不必要的全局变量
尽量避免static成员变量引用资源耗费过多的实例,比如Context。
Android提供了很健全的消息传递机制(Intent)和任务模型(Handler),可以通过传递或事件的方式,防止一些不必要的全局变量。
11、资源的回收,不用过多指望gc:
Java的gc使用的是一个有向图,判断一个对象是否有效看的是其他的对象能到达这个对象的顶点
显示让系统回收:
if(bitmap.isRecycled()==false) { //如果没有回收 bitmap.recycle(); }
12、了解Java四种引用方式
强引用、软引用、弱引用和虚引用
13、使用实体类比接口好
//接口
Map map1 = new HashMap();
//接口
HashMap map2 = new HashMap();
14、避免使用枚举:
枚举变量非常方便,但不幸的是它会牺牲执行的速度和并大幅增加文件体积
public class Foo { public enum Shrubbery { GROUND, CRAWLING, HANGING } }
/////改进:
使用ordinal()方法获取枚举变量的整数值会更好一些:
int valX = MyEnum.VAL_X.ordinal(); int valY = MyEnum.VAL_Y.ordinal(); int count = list.size(); MyItem items = list.items(); for(int n =0; n < count; n++) { intvalItem = items .e.ordinal(); if(valItem == valX) { // do something } else if(valItem == valY) { // do something } }
15、在私有内部内中,考虑用包访问权限替代私有访问权限
public class Foo { public class Inner { public void stuff() { Foo.this.doStuff(Foo.this.mValue); } } private int mValue; public void run() { Inner in = new Inner(); mValue = 27; in.stuff(); } private void doStuff(int value) { System.out.println("value:"+value); } }
//////分析:
可以通过声明被内部类访问的字段和成员为包访问权限,而非私有。但这也意味着这些字段会被其他处于同一个包中的类访问,因此在公共API中不宜采用。
16、适量使用缓存:
17、关闭资源对象:
对SQLiteOpenHelper,SQLiteDatabase,Cursor,文件,I/O操作等都应该记得显示关闭。
相关文章推荐
- 关于java.io.IOException: open failed: EACCES (Permission denied)问题的解决
- libevent代码阅读(9)——“hello-world.c”之 创建事件处理器
- java学习 大问题 @Service @Autowired @Override spring的装配
- 自学php-lamp环境搭建
- Ehcache 整合Spring 使用页面、对象缓存
- 小记Matlab和C混合编程
- spring XML格式
- Eclipse中安装Lua Eclipse插件
- 用C语言实现对冗余层发送的数据包进行过滤判断处理
- C++中的友元
- STL容器之map与hash_map
- Spring3.x中各个jar包的作用总结
- Ackerman的递归与非递归算法
- python简单爬虫技术
- C#反射
- JavaMail发送邮件
- PHP中SSO Cookie登录分析和实现
- 支持sftp协议的libcurl编译
- 支持sftp协议的libcurl编译
- 支持sftp协议的libcurl编译