Android开发之ListView中Adapter的优化
ListView是Android开发最常用的控件,适配器adapter是将要显示的数据映射到View中并添加到ListView中显示
在实现ListView时,我们需要定义适配器如BaseAdapter、ArrayAdapter、CursorAdapter、SimpleAdapter等,并且重写其一下四个方法:
1 public int getCount();
2 public Object getItem(int position)
3 public long getItemId(int position)
4 public View getView(int position, View convertView, ViewGroup parent)
我们需要定义一个View,用来显示每条信息,最后添加到ListView中。
比如我们定义了一个view文件:list_item_callsms.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:layout_marginTop="3dip" android:layout_marginLeft="10dip" android:id="@+id/tv_black_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="黑名单号码" android:textColor="#88000000" android:textSize="20sp" /> <TextView android:layout_marginTop="3dip" android:layout_marginLeft="10dip" android:id="@+id/tv_black_mode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/tv_black_number" android:text="拦截模式" android:textColor="#88000000" android:textSize="15sp" /> </RelativeLayout>
private List<BlackNumberInfo> infos; private class CallSMSSafeAdapter extends BaseAdapter { @Override public int getCount() { // 返回多少条 return infos.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } //有多少个条目 这个方法就会被调用多少次 @Override public View getView(int position, View convertView, ViewGroup parent) { //把一个布局文件转换成一个 view对象 每次都要调用 非常占用内存空间 View view = View.inflate(getApplicationContext(), R.layout.list_item_callsms, null); TextView tv_black_number = (TextView) view .findViewById(R.id.tv_black_number); TextView tv_black_mode = (TextView) view .findViewById(R.id.tv_black_mode); tv_black_number.setText(infos.get(position).getNumber()); String mode = "全部拦截"; if (infos.get(position).getMode().equals("1")) { mode = "电话拦截"; } else if (infos.get(position).getMode().equals("2")) { mode = "短信拦截"; } tv_black_mode.setText(mode); return view; } }
上面会出现一个问题,当要显示的数据集合超过100多条时(infos),当我们快速的滑动ListView时,界面会显示程序无响应,而LogCat中则不停的打印DVM虚拟机GC垃圾回收数据(实际是每次定义的View对象);这样别然严重的影响程序的性能和用户体验;
所以针对上述,可以对ListView使用的Adapter做两方面的优化:
1、 减少内存中View对象的创建次数个数。
ListView中的View在第一个可见的列表里是创建的(converView是为null的),当再次加载滑动时,会converView会复用之间创建的view,之后循环这个可见的View对象列表。
getViewTypeCount()
and getItemViewType(int)
).
2、减小view中对应控件查找的次数。
每次查找view中的控件都是相当耗时的,相当于遍历了一遍view对应的xml树,所以我们只需在第一个遍历,以后直接复用。
因此我们可以创建一个View缓存,然后使用view的Tag存放的控件在内存中的地址。所以我们最多创建ViewList可见的长度个View,查找一次View中控件的id。
这样就能很大的提升程序的性能。
优化后的代码如下:
private class CallSMSSafeAdapter extends BaseAdapter { @Override public int getCount() { // 返回多少条 return infos.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } //有多少个条目 这个方法就会被调用多少次 @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; //把一个布局文件转换成一个 view对象 每次都要调用 非常占用内存空间 //1. 减小内存中View对象创建的个数 if(convertView == null){ //converView 为空时 才创建 convertView = View.inflate(getApplicationContext(), R.layout.list_item_callsms, null); holder = new ViewHolder(); //2. 减小View中控件查询的次数 holder.tv_number = (TextView) convertView .findViewById(R.id.tv_black_number); holder.tv_mode = (TextView) convertView .findViewById(R.id.tv_black_mode); //把ViewHolder保存在View的tag中 convertView.setTag(holder); }else { //获取View的Tag中的ViewHolder holder = (ViewHolder) convertView.getTag(); } holder.tv_number.setText(infos.get(position).getNumber()); String mode = "全部拦截"; if (infos.get(position).getMode().equals("1")) { mode = "电话拦截"; } else if (infos.get(position).getMode().equals("2")) { mode = "短信拦截"; } holder.tv_mode.setText(mode); return convertView; } } /** * 记录View中控件的内存地址 相当于一个记事本 * @author zty * */ static class ViewHolder{ TextView tv_number; TextView tv_mode; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。