安卓开发,listview的优化,减少内存消耗,复用convertView、ViewHolder和分页加载

时间:2022-10-06 22:44:05

1:复用convertView,可以减少view对象的创建。adapter中的getview()方法会传经来一个convertView,convertView是指曾经使用过的view对象,可以被重复使用。但是使用之前要判断是否为空,否则可能会报空指针异常,不为空就直接复用,并作为getview方法的返回对象。
2:复用ViewHolder让其减少findViewById()次数,通过上面的代码可以看到,我们把findViewById找到的对象直接作为ViewHolder的属性赋值给他,然后convertView.setTag(holder);把ViewHolder的对象存储到convertView上,因为convertView是系统帮我们保存的,所以tag也会被保存,然后在复用convertView的时候也可以将上一次的findViewById找到的对象重复使用,这样大大提高了程序的运行效率。

            @Override
public View getView(final int position, View convertView, final ViewGroup parent) {
ViewHolder holder=null;
//复用convertView
if (convertView==null){
holder=new ViewHolder();
convertView = View.inflate(getApplicationContext(), R.layout.listview_blacknumber_item, null);
holder.tv_phone = (TextView) convertView.findViewById(R.id.tv_phone);
holder.tv_mode = (TextView) convertView.findViewById(R.id.tv_mode);
holder.iv_delete = (ImageView) convertView.findViewById(R.id.iv_delete);
convertView.setTag(holder);
}else {
//复用viewHolder
holder= (ViewHolder) convertView.getTag();
}
holder.iv_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//从数据库中删除
mDB.delete(mNumberInfoList.get(position).phone);
//从集合中删除
mNumberInfoList.remove(position);
//通知适配器刷新数据
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
});

listview条目的布局代码:

            //显示数据
holder. tv_phone.setText(mNumberInfoList.get(position).phone);
switch (Integer.parseInt(mNumberInfoList.get(position).mode)) {
case 1:
holder.tv_mode.setText("拦截短信");
break;
case 2:
holder.tv_mode.setText("拦截电话");
break;
case 3:
holder.tv_mode.setText("拦截所有");
break;
}

return convertView;
}

3:static ViewHolder
在ViewHolder类加上static关键字,表示该类只指向一份指定的内存空间,不会创建多个对象,这是对ViewHolder对象创建过程中的一个优化。
4:分页算法
我们可以根据相应的业务需求,分多次加载条目个数,每次加载一个固定的条目,当用户滑动到本次加载条目的最后一条的时候,在继续加载剩下的数据,每次加载一个固定的条目个数,已到达优化的效果,下面我以加载数据库中的数据为例。

        //监听其滚动状态
lv_black_number.setOnScrollListener(new AbsListView.OnScrollListener() {
//滚动过程中,状态发生改变调用方法()
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// OnScrollListener.SCROLL_STATE_FLING 飞速滚动
// OnScrollListener.SCROLL_STATE_IDLE 空闲状态
// OnScrollListener.SCROLL_STATE_TOUCH_SCROLL 拿手触摸着去滚动状态
if(mNumberInfoList!=null){
if (scrollState== AbsListView.OnScrollListener.SCROLL_STATE_IDLE&&
//最后显示的条目的索引
lv_black_number.getLastVisiblePosition()>=mNumberInfoList.size()-1
&&!mIsLoad) {
/*mIsLoad防止重复加载的变量
如果当前正在加载mIsLoad就会为true,本次加载完毕后,再将mIsLoad改为false
如果下一次加载需要去做执行的时候,会判断上诉mIsLoad变量,是否为false,如果为true,就需要等待上一次加载完成,将其值
改为false后再去加载*/

//如果条目总数大于集合大小的时,才可以去继续加载更多
if(mCount>mNumberInfoList.size()){
new Thread(){
@Override
public void run() {
//获取操作黑名单数据库的对象
mDB = BlackNumberDao.getInstance(getApplicationContext());
//查询部分数据
List<BlackNumberInfo> moreData = mDB.find(mNumberInfoList.size());
//把获得的数据添加到集合
mNumberInfoList.addAll(moreData);
//通知适配器刷新数据
mHandler.sendEmptyMessage(0);
}
}.start();

}


}
}
}
//滚动过程中调用方法
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

}
});