Xiao bailong

ListView优化分页优化

缘由

我们在用ListView展现数据的时候。比如展现联系人,如果联系人太多就会出现卡的现象,比如如果有1000多条数据,从数据库里查询,然后装载到List容器这段时间是比较耗时的。虽然我们可以用asyncTask来单独开启一个子线程加载。一次查看那么多,未免有点多余。是否可以通过先装载30条数据,如果用户需要我们在继续查询并且展示后面的数据,这样一来可以提升。使用速率。

实现方法

1、数据库分页查询

首先写SqlHelper指定每次查询数据库多少数据。代码如下

/**
* 分页查询黑名单
*
* @param limit
* 限制数量
* @param offset
* 开始位置
* @return
*/

public List<BlackNumInfo> getPartBlackNum(int limit, int offset)
{
//查询返回的数据容器
List<BlackNumInfo> blackNums = null;
SQLiteDatabase db = dbHelper.getReadableDatabase();

String[] columns = new String[] { NUM, MODE, ID };
String selection = null;
String[] selectionArgs = null;
String groupBy = null;
String having = null;
String orderBy = null; // 排序功能
String limitsr = offset + "," + limit; // 分页数据

Cursor cursor = db.query(TABLE, columns, selection, selectionArgs, groupBy, having,
orderBy, limitsr);
//如果没有数据就返回View
if (cursor.getCount() > 0)
{
blackNums = new ArrayList<BlackNumInfo>();
}

while (cursor.moveToNext())
{
String num = cursor.getString(0);
int mode = cursor.getInt(1);
int id = cursor.getInt(2);
BlackNumInfo b = new BlackNumInfo(num, mode, id);
blackNums.add(b);
}

db.close();
dbHelper.close();
return blackNums;
}

2. AsyncTask类的内部优化

  • 思路:每次开启一个异步任务查询数据。
  • 重置适配器中,数据容器的值,刷想适配器
  • ListView重绘
/**
* 异步加载
*/

public void fillData()
{
new AsyncTask<String, Integer, String>()
{

// 程序运行前
@Override
protected void onPreExecute()
{
mLoadProgressBar.setVisibility(View.VISIBLE);
// 显示加载进度
super.onPreExecute();
}

// 程序运行时
@Override
protected String doInBackground(String... params)
{
// 查询 前30项的数据: 用子线程 ,
if (mBlackNumList == null)
{
mBlackNumList = dao.getPartBlackNum(limit, offset);
} else
{
// 如果不是第一次查询
if (dao.getPartBlackNum(limit, offset) != null)
{
//把查询到的数据添加到容器中去
mBlackNumList.addAll(dao.getPartBlackNum(limit, offset));
}
}

return null;
}

// 运行后
@Override
protected void onPostExecute(String result)
{
//ProgressBar设置为不可见。
mLoadProgressBar.setVisibility(View.INVISIBLE);

if (adapter == null)
{
//第一次加载,创建适配器适配器
adapter = new BlackNumAdapter(context, mBlackNumList);
mBlackNumListView.setAdapter(adapter);
} else
{
//第二次加载,适配器中容器数量
adapter.setBlackNumList(mBlackNumList);
//发送通知,适配器内容改变,从新加载
adapter.notifyDataSetChanged();
}
}

}.execute();
}

3.Adapter优化分页数据

  • 思路
  • convertView可回收视图的再次利用。
  • holderView类保存每次inflate出来View的子控件并保存在convertViewTag中。
  • 添加一个setDate()方法,重置容器数据

public class BlackNumAdapter extends BaseAdapter
{
List<BlackNumInfo> mBlackNumList;
Context context;
BlackNumDao dao;

public BlackNumAdapter(Context context, List<BlackNumInfo> mBlackNumList)
{
this.context = context;
dao = new BlackNumDao(context);
this.mBlackNumList = mBlackNumList;
}

public void setBlackNumList(List<BlackNumInfo> mBlackNumInfos)
{
this.mBlackNumList = mBlackNumInfos;
}

@Override
public int getCount()
{
return mBlackNumList.size();
}

@Override
public Object getItem(int position)
{
return mBlackNumList.get(position);
}

@Override
public long getItemId(int position)
{
return position;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent)
{
// 适配器的优化
final BlackNumInfo numInfo = mBlackNumList.get(position);
holderView hV = null;
if (convertView == null)
{
hV = new holderView();
convertView = LayoutInflater.from(context).inflate(R.layout.item_blacknum, parent,
false);
hV.modeTextView = (TextView) convertView.findViewById(R.id.tv_mode);
hV.numberTextView = (TextView) convertView.findViewById(R.id.tv_number);
hV.deleteImageView = (ImageView) convertView.findViewById(R.id.iv_deleteNumber);
convertView.setTag(hV);
} else
{
hV = (holderView) convertView.getTag();
}

hV.numberTextView.setText(mBlackNumList.get(position).getNum());

String mode = "全部拦截";
switch (numInfo.getMode())
{
case BlackNumDao.ALL:
mode = "全部链接";
break;
case BlackNumDao.CLL:
mode = "电话拦截";
case BlackNumDao.SMS:
mode = "短信拦截";
default:
break;
}

hV.modeTextView.setText(mode);
hV.deleteImageView.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// 删除功能
dao.delete(numInfo.getNum() + "");
mBlackNumList.remove(position);
notifyDataSetChanged();
}
});
return convertView;
}

}

/**
* 包装类
* @author H_lang
*
*/

class holderView
{
public TextView modeTextView;
public TextView numberTextView;
public ImageView deleteImageView;
}

4.ListView滚动监听。

  • liseView设置滚动监听。
  • 重置分页查询的开始标度

/**
* 滚动状态改变的时候。
*/

@Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
// 根据滚动的状态来加载数据。
if (scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL)
{
// 获得最后一次显示的数据
int lastVisiblePosition = mBlackNumListView.getLastVisiblePosition();
int size = mBlackNumList.size();

if (lastVisiblePosition == size - 1)
{
//设置下次查询的开始位置。
offset = limit + offset;
fillData();
}

}

}

总结

其中还是有许多的缺点。还有许多需要优化的功能。但是对于我现在学习的技术,没有想到更好的方法,希望以后我能继续优化,或者重写listView控件。

posted @ 2015-09-13 00:17  小白龙on  阅读(247)  评论(0编辑  收藏  举报

QQ:846650266,电话:15117424475

© 白龙工作室 |隐私条款 |服务条款 |盘ICP备10000000号-1