缘由
我们在用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
的子控件并保存在convertView
的Tag
中。- 添加一个
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
控件。
时间: 2024-10-14 06:26:49