ListView这个布局经常用到,这个布局中有一个方法getView需要我们来实现,如果使用没有优化的ListView,还是比较消耗内存。下面说一下优化ListView的方法:
主要从两个方面:
首先没有之前的getView方法:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = View.inflate(SelectContactActivity.this, R.layout.list_item_contact, null);
TextView tv_contact_name = (TextView) view.findViewById(R.id.tv_contact_name);
tv_contact_name.setText(contactInfo.get(position).get("name"));
TextView tv_contact_num = (TextView) view.findViewById(R.id.tv_contact_num);
tv_contact_num.setText(contactInfo.get(position).get("phone"));
return view;
}
1、使用contentView缓存对象。
listview工作原理:当最上面或者最下面的一个Item被覆盖之后,系统会自动将其缓存起来,其实就缓存给了contentView,那么当我们每一次调用getView方法时就可以使用这个缓存对象,而不用每次都创新新的View对象,可以起到很好的优化内存的作用。
代码如下:
if(convertView != null){
view = convertView;
//System.out.println("缓存");
}else {
view = View.inflate(AppManagerActivity.this,R.layout.item_app_manager , null);
holder = new ViewHolder();
tv_app_name = (TextView) view.findViewById(R.id.tv_app_name);
tv_app_rom = (TextView) view.findViewById(R.id.tv_app_rom);
iv_app = (ImageView) view.findViewById(R.id.iv_app);
bt_uninstall = (Button) view.findViewById(R.id.bt_uninstall);
iv_app_lock = (ImageView) view.findViewById(R.id.iv_app_lock);
//System.out.println("新建");
}
2、使用ViewHolder缓存对象。
先直接上代码, 先定义 ViewHolder对象,相当于一个口袋,用于记录空间的对象,用这种方法效率提升不是很大,大概提升5%。
/**
* view对象的容器
*记录孩子的内存地址。
*相当于一个记事本
*/
static class ViewHolder{
TextView tv_app_name;
TextView tv_app_rom;
ImageView iv_app;
Button bt_uninstall;
ImageView iv_app_lock;
}
View view;
ViewHolder holder;
if(convertView != null){
view = convertView;
holder = (ViewHolder) view.getTag();
//System.out.println("缓存");
}else {
view = View.inflate(AppManagerActivity.this,R.layout.item_app_manager , null);
holder = new ViewHolder();
holder.tv_app_name = (TextView) view.findViewById(R.id.tv_app_name);
holder.tv_app_rom = (TextView) view.findViewById(R.id.tv_app_rom);
holder.iv_app = (ImageView) view.findViewById(R.id.iv_app);
holder.bt_uninstall = (Button) view.findViewById(R.id.bt_uninstall);
holder.iv_app_lock = (ImageView) view.findViewById(R.id.iv_app_lock);
//iv_app_lock
view.setTag(holder);
//System.out.println("新建");
}
3、使用分页加载与分批加载
分页加载与分批相互对立,无非时间换空间,空间换时间的问题。
首先是分页加载,顾名思义,就是一页一页的加载,触发某个事件,便会加载一部分数据,但是缺点是加载了下一页,那么上一页的数据也就丢掉了,如果要返回上一页,还要继续请求数据库,造成了时间的消耗,但是优点却是节省了内存。
对于分批加载,相对于分页加载,其实就是没有丢掉上一页的数据,那么返回上一页,就会立刻响应,在内存足够的情况下,分批加载用户体验较好。
无论是分页还是分批加载,都是动态加载数据,都比一次性加载全部数据到listView要节省内存,对于优化ListView也是功不可没。
4、使用scrollListener,记住滑动的状态
scrollListener与分页加载或者分批加载一起使用,相当于scrollListener作为上述的触发事件,当滑动到每个状态的开始继续加载数据。
说什么都没有上代码来的直接
lv_black_num.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case OnScrollListener.SCROLL_STATE_FLING://惯性滑动状态
int lastPositon = lv_black_num.getLastVisiblePosition();
if(lastPositon == blackNumList.size() - 1) {
//继续加载数据
System.out.println("继续加载数据");
if(dataFlag) {
offset += maxNumList;
//System.out.println("继续加载数据");
fillData();
}else {
//tv_loaddata.setText("没有更多数据了");
//System.out.println("没有更多数据了");
Toast.makeText(CommunicationSafeActivity.this, "没有更多数据了", 1).show();
}
}
break;
case OnScrollListener.SCROLL_STATE_IDLE://空闲状态
break;
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL://手指滑动状态
break;
default:
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});