黑名单管理优化
优化1:View view = View.inflate(getApplicationContext(), R.layout.listview_callsms_activity_item, null); 如果将xml布局转成view对象,让自己来写: 1)以流形式关联xml文件,将其加载到内存 2)将xml文件中的内容用pull解析出来,一个个对象 3)根据xml中的属性和内容给相应的对象设置 可以发现,如果ListView内容过多,拖动的数据过快, 也就是 public View getView(int position, View convertView, ViewGroup parent){} 方法不断地执行,此时耗费很大的内存,可能会出现dalvikvm虚拟机内存不足的异常。 解决:getView方法中,View convertView代表的就是用户不可见的view对象 getViewTypeCount()
and getItemViewType(int) ). |
核心代码: @Override
public View getView(int position, View convertView, ViewGroup parent) {
// 1、转换xml为view对象
//进行复用以前创建的view对象
View view = null;
if (convertView!=null && convertView instanceof RelativeLayout) {//a) 如果不为null,且类型正确,那么复用该view对象
view = convertView;
Log.i(TAG, "复用旧的view对象:" + position);
}else { //b) 否则,就创建一个
view = View.inflate(getApplicationContext(), R.layout.listview_callsms_activity_item, null);
Log.i(TAG, "新创建的view对象:" + position);
}
// 2、通过view找到里面的组件
TextView tv_number = (TextView) view.findViewById(R.id.tv_listitem_blacknumber);
TextView tv_mode = (TextView) view.findViewById(R.id.tv_listitem_blackmode);
// 3、获取对应位置的BlackNumberInfo对象
BlackNumberInfo blackNumberInfo = numberInfos.get(position);
// 4、设置数据
tv_number.setText(blackNumberInfo.getNumber());
String mode = blackNumberInfo.getMode();
if ("1".equals(mode)) {
mode = "电话拦截";
} else if ("2".equals(mode)) {
mode = "短信拦截";
} else if ("3".equals(mode)) {
mode = "全部拦截(电话拦截+短信拦截)";
}
tv_mode.setText(mode);
// 5、返回view对象,一定要返回
return view;
}
|
结果: |
问题2:查找孩子也是很耗内存的,一颗树,通过算法来查找孩子,所以需要将其保存起来 TextView tv_number = (TextView) view.findViewById(R.id.tv_listitem_blacknumber);
TextView tv_mode = (TextView) view.findViewById(R.id.tv_listitem_blackmode);1)定义一个ViewHolder来保存 /**
* 3、保存着TextView对象的引用,优化,使用static效率更高些
* @author hacket
*/
private static class ViewHolder {
TextView tv_number;// 黑名单拦截号码
TextView tv_mode;// 黑名单拦截模式
}2)在新建View的时候,创建ViewHolder,并通过id查找对象的组件, // ba)新建view对象时,new出来viewholder,保存引用 viewHolder = new ViewHolder();
viewHolder.tv_number = (TextView) view.findViewById(R.id.tv_listitem_blacknumber);
viewHolder.tv_mode = (TextView) view.findViewById(R.id.tv_listitem_blackmode);
// bb) view关联起来viewholder view.setTag(viewHolder); //A tag can be used to mark a view in its hierarchy and does not have to be unique within the hierarchy. 3) 在复用的时候,查找到view绑定的tag对应的对象ViewHolder viewHolder = (ViewHolder) view.getTag();// 获取view关联的tag,viewholder,里面保存着,之间找到的组件,就不用再去find组件了 |
核心代码: /**
* 2、黑名单显示ListView的Adapter适配器
* @author hacket
*/
private class CallSmsSafeAdapter extends BaseAdapter {
private static final String TAG = "CallSmsSafeActivity";
@Override
public int getCount() {
if (numberInfos!=null) {
return numberInfos.size();
}
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 1、转换xml为view对象
//进行复用以前创建的view对象
View view = null;
ViewHolder viewHolder = null;
if (convertView!=null && convertView instanceof RelativeLayout) { //a) 如果不为null,且类型正确,那么复用该view对象
Log.i(TAG, "复用旧的view对象:" + position);
view = convertView;
// 在复用的时候,查找到view绑定的tag对应的对象ViewHolder
viewHolder = (ViewHolder) view.getTag(); // 获取view关联的tag,viewholder,里面保存着,之间找到的组件,就不用再去find组件了
} else { // b) 否则,就新创建一个view对象
Log.i(TAG, "新创建的view对象:" + position);
view = View.inflate(getApplicationContext(), R.layout.listview_callsms_activity_item, null);
// ba)新建view对象时,new出来viewholder,保存引用
viewHolder = new ViewHolder();
viewHolder.tv_number = (TextView) view.findViewById(R.id.tv_listitem_blacknumber);
viewHolder.tv_mode = (TextView) view.findViewById(R.id.tv_listitem_blackmode);
// bb) view关联起来viewholder
view.setTag(viewHolder); //A tag can be used to mark a view in its hierarchy and does not have to be unique within the hierarchy
}
// 2、通过view找到里面的组件,很耗内存和时间
//TextView tv_number = (TextView) view.findViewById(R.id.tv_listitem_blacknumber);
//TextView tv_mode = (TextView) view.findViewById(R.id.tv_listitem_blackmode);
// 3、获取对应位置的BlackNumberInfo对象
BlackNumberInfo blackNumberInfo = numberInfos.get(position);
// 4、设置数据
viewHolder.tv_number.setText(blackNumberInfo.getNumber());
String mode = blackNumberInfo.getMode();
if ("1".equals(mode)) {
mode = "电话拦截";
} else if ("2".equals(mode)) {
mode = "短信拦截";
} else if ("3".equals(mode)) {
mode = "全部拦截(电话拦截+短信拦截)";
}
viewHolder.tv_mode.setText(mode);
// 5、返回view对象,一定要返回
return view;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
}
|
结果: |
优化3:允许ListView快速拖动android:fastScrollEnabled="true" <ListView
android:fastScrollEnabled="true"
android:id="@+id/lv_callsmssafe_activity"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>之后在右边就会有一个小方块,可以拖动的 |
总结:ListView的优化
1、 View convertView,view对象的复用 a) 判空 b) 判断类型 2、ViewHolder,用来保存已经通过id查找到的组件 3、ListView的 android:fastScrollEnabled = "true" 属性,允许快速滚动,默认为false |