1. 资源对象没有关闭造成的内存泄漏
资源对象如Cursor、File等,往往都用了一些缓存,不用时应该及时关闭它们。先close()再设置为null
2. 不良代码造成内存压力
a. Bitmap没有调用recycle()
Bitmap对象不再使用时,应该先调用recycle()释放内存,然后测试结果显示它没有立即释放内存,但是应该还是能大大的加速Bitmap主要内存的释放。
b. 构造Adapter时,没有使用缓存的convertView
以构造ListView的BaseAdapter为例,在BaseAdapter中提共了方法:
public View getView( int position, View convertView, ViewGroup parent)
来向ListView提供每一个item所需要的view对象。初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化 一定数量的view对象,同时ListView会将这些view对象缓存起来。当向上滚动ListView时,原先位于最上面的list item的view对象会被回收,然后被用来构造新出现的最下面的list item。这个构造过程就是由getView()方法完成的,getView()的第二个形参View convertView就是被缓存起来的list item的view对象(初始化时缓存中没有view对象则convertView是null)。
由此可以看出,如果我们不去使用convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费时间,也造 成内存垃圾,给垃圾回收增加压力,如果垃圾回收来不及的话,虚拟机将不得不给该应用进程分配更多的内存,造成不必要的内存开支。
layout.xml
<?xml version="1.0" encoding="utf-8" ?>能引起内存泄露的代码: BadAdapter.java
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="60dip">
<ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:paddingLeft="9px" />
<TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/icon" android:textAppearance="?android:attr/textAppearanceMedium" android:paddingLeft="9px" />
</RelativeLayout>
public class BadAdapter extends BaseAdapter {
......
@Override
public View getView(int position, View convertView, ViewGroup parent) {public class GoodAdapter extends BaseAdapter {
Log.d("MyAdapter", "Position:" + position + "---"
+ String.valueOf(System.currentTimeMillis()));
final LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.list_item_icon_text, null);
((ImageView) v.findViewById(R.id.icon)).setImageResource(R.drawable.icon);
((TextView) v.findViewById(R.id.text)).setText(mData[position]);
return v;
}
}
修正优化示例代码示例代码:GoodAdapter.java
......
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("MyAdapter", "Position:" + position + "---"
+ String.valueOf(System.currentTimeMillis()));
ViewHolder holder;
if (convertView == null) {
final LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
holder.text = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.icon.setImageResource(R.drawable.icon);
holder.text.setText(mData[position]);
return convertView;
}
static class ViewHolder {
ImageView icon;
TextView text;
}
}
3. ThreadLocal使用不当
如果我们粗暴的把ThreadLocal设置null,而不调用remove()方法或set(null),那么就可能造成ThreadLocal绑定的对象长期也能被回收,因而产出内存泄露。