本帖最后由 武汉分校-小舞 于 2016-3-18 11:16 编辑
【武汉校区】独家分享:Android的有关内存性能的总结
作为一名Android开发人员,我们都知道Android系统对每个软件所能使用的RAM空间进行了限制(如:Nexus one 对每个软件的内存限制是24M),同时Java语言本身比较消耗内存, dalvik虚拟机也要占用一定的内存空间。所以,在这里我就跟大家聊一聊在Android开发当中遇到的有关内存优化方面的个人总结,仅仅是个人总结….如果你有不同意见,请大家各自保留。那么,对于Android的内存优化,我个人总结出了一个基本准则 第一:不要做不必要的事。第二:不要分配不必要的内存。 下面,我就基于这2点准则,为大家列举一下开发当中所需要的一些点: 那么首先,我们都知道开发Android程序的IDE工具有eclipse、idea以及google新推的android studio…那么从开发的工具选择上呢,我建议大家使用studio工具,至于原因的话,相信我不用多少,大家都能够明白? 谁能对自己的亲儿子不多加照顾呢? 那么好的,确定了开发的IDE工具之后,那么在开发过程当中,我个人所遇到的一些跟内存优化相关的技术点,来跟大家一一罗列一下吧… First: 避免创建不必要的对象,特别是for循环里当中组装数据到集合当中的时候,每一次for循环都new出来一个对象,从而每一次都创建了一个这个对象的引用,这种做法不太好,而我们通常大多数在编写代码的时候,都会这么写,请看示例代码: for (int i = 0; i < datas.length; i++) {
Product bean = new Product();
//.....set.set
} 优化后的写法: Product bean = null;
for (int i = 0; i < datas.length; i++) {
bean = new Product();
//.....set.....set
//list集合加入当中
list.add(bean);
} Two:尽量多使用静态方法调用,静态调用比普通方法调用要快,因为调用静态方法可以无需创建对象,在执行效率上更高。 Three:Android当中bean对象定义,避免使用gettters/setters,可以将变量定义成public直接访问比调用getters/setters更加高效些。 那么就直接上代码吧,在我们习惯的变成开发中,定义bean通常对象是这样的: public class Image {
private String ID;
private String IMAPAURL;
private String IMAURL;
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
public String getIMAPAURL() {
return IMAPAURL;
}
public void setIMAPAURL(String IMAPAURL) {
this.IMAPAURL = IMAPAURL;
}
public String getIMAURL() {
return IMAURL;
}
public void setIMAURL(String IMAURL) {
this.IMAURL = IMAURL;
}
} 个人优化后的写法: */
public class Image {
public String ID;
public String IMAPAURL;
public String IMAURL;
} 简单,代码量少,而且执行效率更高。 Four:尽量多利用缓存 这个我相信不用多少了,就拿我写的其中一个viewpagerAdapter适配器来说吧,当我需要适配出来几千甚至上万张图片的时候,我但是不能用上万个ImageView对象去做了,这是我利用缓存的适配器代码,大家可以参考: public class PlayingAdapter extends PagerAdapter {
private Context context;
private List<MediaSession.QueueItem>queue;
private List<ImageView> cache = new ArrayList<>();
public PlayingAdapter(Context context, List<MediaSession.QueueItem>queue) {
this.context = context;
this.queue = queue;
}
@Override
public int getCount() {
return queue == null ? 0 : queue.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
//从缓存当中查一下,如果缓存有图片的话,直接使用缓存的,使用完毕之后,再从缓存集合当中移除
//如果缓存没有的话,new一个
ImageView result = null;
if(cache.size()==0){
result = new ImageView(context);
result.setScaleType(ImageView.ScaleType.CENTER_CROP);
}else{
result = cache.remove(0);
}
Picasso.with(context).load(queue.get(position).getDescription().getIconUri()).into(result);
container.addView(result);
return result;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((ImageView)object);
cache.add((ImageView) object);
}
public void flushData(List<MediaSession.QueueItem>queue) {
this.queue = queue;
notifyDataSetChanged();
}
} Five:定义常量尽量多使用static final,避免使用枚举,普通成员变量避免过多的使用static关键子,特别是Context, 如果用它来引用一些资源耗费过多的实例。 在java中枚举类的过多使用会降低程序的执行效率,从而影响我们开发当中的软件性能,所以应该尽量避免过多的使用枚举类,如果是常量的话,可以多使用static final ,但是如果是普通变量,应该必变过多的使用static修饰,因为静态变量如果没有被销毁或者设置为null,它的引用一直存在,如果过多的有这种情况出现,就会导致内存泄露的问题了,而且如果经常使用static的Bitmap、Drawable等变量。可能就会抛出一个在Android系统中非常著名的异常(以前budget这个单词一直记不住什么意思,自从经常抛出这个异常后,这个单词终于烂熟于心了
ERROR/AndroidRuntime(4958): Caused by: java.lang.OutOfMemoryError:bitmap size exceeds VM budget six:资源对象必须关闭,SQLiteOpenHelper,cursor,文件,i/o流等等 相信这个都不用多说了,我个人总结一点,所有使用了操作流数据的对象使用完毕后,统统都需要关闭。 Seven:bitmap大图片用完需要recycle回收,并设置为null,方便gc回收 这个相信大家也都比较熟悉了,其实不止是bitmap,Android当中TypedArray对象等等,使用完毕之后,都是建议我们调用recycle方法进行回收的,只是容易被大家忽略的是,将其设置为null,当然这个不是一定的,要根据你的具体情况来定了,如果你不需要再使用到它的话,就将其设置为null….让gc来回收掉它吧… Eight:注册广播接收者,必须取消反注册,避免内存泄露。 这个我相信大家也都知道,每每调用registXX---那么千万要养成好的习惯,在onDestory当中进行反注册 unRegistXX….,那么如果不这样写的话,就会出现内存泄露的问题了。 Nine:listview的列表优化都需要做等等。 相信这个不需要我再废话多少了…就是利用缓存机制,那么我总结一点的就是,当使用listview开发真实的app项目的话,都必须要做优化… 以上就是本人对于Android开发当中的内存性能的几点总结了,希望提供大家参考,为程序员同胞们能带去帮助。
想最快获传智播客武汉中分享技术文章请加QQ 1641907557 ,后期会分享更多与实体班同步教程,助你冲击月薪20K!
|