1.Andorid内存与性能优化
今天看到一篇介绍Android
内存优化的文章,觉得对于以后的学习很有帮助,决定收藏起来并总结一些知识点。点击查看原文
GC 的工作机制
当 GC 工作时,虚拟机停止其他工作。频繁地触发 GC 进行内存回收,会导致系统性能严重下降。
应该避免GC做不必要的工作。
内存抖动
在极短的时间内,分配大量的内存,然后又释放它,这种现象就会造成内存抖动。典型地,在 View 控件的 onDraw 方法里分配大量内存,又释放大量内存,这种做法极易引起内存抖动,从而导致性能下降。因为 onDraw 里的大量内存分配和释放会给系统堆空间造成压力,触发 GC 工作去释放更多可用内存,而 GC 工作起来时,又会吃掉宝贵的帧时间 (帧时间是 16ms) ,最终导致性能问题。内存泄漏
Java 语言的内存泄漏概念和 C/C++ 不太一样,在 Java 里是指不正确地引用导致某个对象无法被 GC 释放,从而导致可用内存越来越少。比如,一个图片查看程序,使用一个静态 Map 实例来缓存解码出来的 Bitmap 实例来加快加载进度。这个时候就可能存在内存泄漏。内存泄漏会导致可用内存越来越少,从而导致频繁触发 GC 回收内存,进而导致性能下降。优化内存的几个原则
- 别在循环里分配内存 (创建新对象)
- 尽量别在 View 的 onDraw 函数里分配内存(创建新对象)
- 实在无法避免在这些场景里分配内存时(创建新对象),考虑使用对象池 (Object Pool)
详细的可以见kamidox的Android内存与性能优化
2. ListView 的 BaseAdapter 的优化
因为
BaseAdapter
是经常使用的,里面的具体方法就略过,只记下最主要的getView()
方法先看这段代码
public View getView(int position, View convertView, ViewGroup parent) {
MyInfo userInfo = infos.get(position);
View view;
ViewHolder holder; //减少内存中view对象创建的次数
if (convertView != null && convertView instanceof RelativeLayout) {
view = convertView;//复用已经回收掉的view对象
holder = (ViewHolder) view.getTag();//得到他们的引用
} else {
view = View.inflate(getApplicationContext(), R.layout.item_layout, null);//把布局文件转化成View对象
holder = new ViewHolder(); //把ID存到存到holder对象中
//注意是在view下findViewById
holder.iv = (ImageView) view.findViewById(R.id.imageView1);
holder.tv1 = (TextView) view.findViewById(R.id.textView1);
holder.tv2 = (TextView) view.findViewById(R.id.textView2);
view.setTag(holder);//对象创建出来时找到他们的引用存到holder中
}
holder.tv1.setText(infos.get(position).getName());
holder.tv2.setText(infos.get(position).getNumber());
return view;
}-
其中的
ViewHolder
类如下class ViewHolder{ TextView tv1; TextView tv2; ImageView iv; }
-
getView()
方法的参数-
int position
代表返回的view
是ListView
的第position
项 -
View convertView
代表了一个从对象池里取出来的view
,如果为NULL
,说明没有可使用的view
,则需要实例化一个,否则可以复用这个view
-
ViewGroup parent
就是这个view
的父组件,就是ListView
-
优化则表现在重复使用已经存在的可复用的
view
以及保留引用
getView()
方法中,对convertView
做判断是否为空值,如果为不为空则拿来重复使用,避免大量实例化view
,造成系统资源的浪费,为空则说明对象池中还没有缓存有已经回收的view
,则需要实例化。
那缓存的view
是哪里来的?答案就是:ListView
显示的itemview
的数量一般是固定的,每当上下滑动时,滑动出去显示区域的itemview
就会被缓存在对象池中。
而ViewHolder
则是相当于一本笔记本的存在,将每个view
中的控件引用保留在这个笔记本中,避免每次都要findViewById()
,这是相当耗费资源的操作。