您的位置:首页 > 编程语言

安卓代码优化(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)访问成员变量比访问本地变量慢得多

一般代码:直接访问成员变量

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操作等都应该记得显示关闭。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: