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 } });