您的位置:首页 > 移动开发 > Android开发

android 代码性能优化

2015-04-30 10:01 218 查看
因为android 性能,ANR,生命周期等限制需要在代码中合理优化,保证性能。通过三个方面来讲

一,降低运行的时间

1)缓存

缓存主要包括对象缓存、IO缓存、网络缓存、DB缓存,对象缓存能减少内存的分配,IO缓存减少磁盘的读写次数,网络缓存减少网络传输,DB缓存较少Database的访问次数。

a).消息缓存

通过handler.obtainMessage复用之前的message,如下:

Message msg = new Message();改为Message msg = handler.obtainMessage(); 减少message 实例化的开销

查看obtainMessage()源码:



进入obtain方法:



再进入objtain方法:



b)文件IO缓存

使用具有缓存策略的输入流,BufferedInputStream替代InputStream,BufferedReader替代Reader,BufferedReader替代BufferedInputStream.对文件、网络IO皆适用。

c)layout的缓存 主要是减少view的inflate

d)网络缓存

网络缓存是在网络请求时有缓存机制,策略一般是统一设置缓存的时间(一般为60秒)。也有对每条数据根据服务器返回的缓存时间控制。

遵循Http/1.1 rfc2616规范,根据服务器Response Header中的Cache-Control字段的max-age确定缓存时间,如果不存在就取Response Header中的Expires做为缓存过期时间,

另外如果某次请求不想使用缓存数据或返回数据不想被缓存怎么办

a. 某次请求不想使用缓存

在调用httpGet方法时设置入参HttpRequest,如下:

request.setRequestProperty(“cache-control”, “no-cache”);

b. 某次请求返回数据不想被缓存

在调用httpGet方法时设置入参HttpRequest,如下:

request.setRequestProperty(“cache-control”, “no-store”);

对于一般的策略,因为我是用到xUtils的,所以我们来看下它的缓存策略是怎么做的

主要有三个类 HttpCache.java LruMemoryCache.java KeyExpiryMap.java

在HttpCache.java中

public void put(String url, String result, long expiry) {
if (url == null || result == null || expiry < 1) return;

mMemoryCache.put(url, result, System.currentTimeMillis() + expiry);
}可以看到put的时候把延长时间参数传了进来,其中mMemoryCache是LruMemoryCache的实例
在LruMemoryCache.java中

public final V put(K key, V value, long expiryTimestamp) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
}

V previous;
synchronized (this) {
putCount++;
size += safeSizeOf(key, value);
previous = map.put(key, value);
keyExpiryMap.put(key, expiryTimestamp);
if (previous != null) {
size -= safeSizeOf(key, previous);
}
}

if (previous != null) {
entryRemoved(false, key, previous, value);
}

trimToSize(maxSize);
return previous;
}LruMemoryCache是个map来存储数据,我们看到时间是put到keyExpiryMap中,这个就是KeyExpiryMap的实例。KeyExpiryMap是个map。
我们可以看到时间有效是System.curretTimemisllis()+expiry。

看KeyExpiryMap containsKey的方法是判断时间是否失效的

public synchronized boolean containsKey(Object key) {
boolean result = false;
Long expiryTimestamp = super.get(key);
if (expiryTimestamp != null && System.currentTimeMillis() < expiryTimestamp) {
result = true;
} else {
this.remove(key);
}
return result;
}如果System.currentTimeMillis()<expiryTimestamp 就为有效,否则就remove掉。
e)DB缓存

(2). 数据存储优化

包括数据类型、数据结构的选择。

a. 数据类型选择

字符串拼接用StringBuilder代替String,在非并发情况下用StringBuilder代替StringBuffer。如果你对字符串的长度有大致了解,如100字符左右,可以直接new StringBuilder(128)指定初始大小,减少空间不够时的再次分配。

64位类型如long double的处理比32位如int慢

使用SoftReference、WeakReference相对正常的强应用来说更有利于系统垃圾回收

final类型存储在常量区中读取效率更高

LocalBroadcastManager代替普通BroadcastReceiver,效率和安全性都更高

b. 数据结构选择

常见的数据结构选择如:

ArrayList和LinkedList的选择,ArrayList根据index取值更快,LinkedList更占内存、随机插入删除更快速、扩容效率更高。一般推荐ArrayList。

ArrayList、HashMap、LinkedHashMap、HashSet的选择,hash系列数据结构查询速度更优,ArrayList存储有序元素,HashMap为键值对数据结构,LinkedHashMap可以记住加入次序的hashMap,HashSet不允许重复元素。

HashMap、WeakHashMap选择,WeakHashMap中元素可在适当时候被系统垃圾回收器自动回收,所以适合在内存紧张型中使用。

Collections.synchronizedMap和ConcurrentHashMap的选择,ConcurrentHashMap为细分锁,锁粒度更小,并发性能更优。Collections.synchronizedMap为对象锁,自己添加函数进行锁控制更方便。

Android也提供了一些性能更优的数据类型,如SparseArray、SparseBooleanArray、SparseIntArray、Pair。

Sparse系列的数据结构是为key为int情况的特殊处理,采用二分查找及简单的数组存储,加上不需要泛型转换的开销,相对Map来说性能更优。不过我不太明白为啥默认的容量大小是10,是做过数据统计吗,还是说现在的内存优化不需要考虑这些东西,写16会死吗,还是建议大家根据自己可能的容量设置初始值。

2、异步,利用多线程提高TPS

在Android应用程序中由于系统ANR的限制,将可能造成主线程超时操作放入另外的工作线程中。在工作线程中可以通过handler和主线程交互。

3、提前或延迟操作,错开时间段提高TPS

(1) 延迟操作

不在Activity、Service、BroadcastReceiver的生命周期等对响应时间敏感函数中执行耗时操作,可适当delay。

Java中延迟操作可使用ScheduledExecutorService,不推荐使用Timer.schedule;

Android中除了支持ScheduledExecutorService之外,还有一些delay操作,如

handler.postDelayed,handler.postAtTime,handler.sendMessageDelayed,View.postDelayed,AlarmManager定时等。

(2) 提前操作

对于第一次调用较耗时操作,可统一放到初始化中,将耗时提前。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: