57ListView的分批和分页的加载数据

来源:互联网 发布:java制作计算器 编辑:程序博客网 时间:2024/04/25 15:14

分批加载数据是为了解决用户体验的问题,而分页加载是为了解决OOM的问题。QQ的聊天记录就是采用分页加载数据的,新数据会覆盖旧的数据,而分批加载数据,比如一次加载20条数据,加载20条之后再去加载新的数据。

我们这里是在黑名单列表处理的这种情况,采用分批加载数据:

数据库分批查询:

/** * 查询部分黑名单是否存在 * @param offset 从哪个位置开始获取数据 * @param maxnumber 一次最多获取多少条记录 * @return */public List<BlackNumberInfo> findPart(int offset,int maxnumber) {List<BlackNumberInfo> result = new ArrayList<BlackNumberInfo>();SQLiteDatabase db = helper.getReadableDatabase();Cursor cursor = db.rawQuery("select number,mode from blacknumber order by _id desc limit ? offset ?", new String[]{String.valueOf(maxnumber),String.valueOf(offset)});while (cursor.moveToNext()) {BlackNumberInfo info = new BlackNumberInfo();String number = cursor.getString(0);String mode = cursor.getString(1);info.setMode(mode);info.setNumber(number);result.add(info);}cursor.close();db.close();return result;}

然后给ListView注册一个监听滚动的事件:

// listview注册一个滚动事件的监听器listView.setOnScrollListener(new OnScrollListener() {/** * 当滚动的状态发生变化的时候 *  */@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {switch (scrollState) {// 空闲状态case OnScrollListener.SCROLL_STATE_IDLE:System.out.println("SCROLL_STATE_IDLE");// 判断当前listview滚动的位置// 获取ListView最后一个可见条目在集合里面的位置int lastVisiblePosition = listView.getLastVisiblePosition();System.out.println(lastVisiblePosition);if (lastVisiblePosition == (infos.size() - 1)) {System.out.println("列表被移动到了最后一个位置,加载更多数据。。。");offset += maxnumber;if (offset >= findAll.size()) {Toast.makeText(getApplicationContext(), "亲,数据已经加载完毕啦!", 0).show();ll_loading.setVisibility(View.INVISIBLE);}else {fillData();}//System.out.println("offset:" + offset);//System.out.println("列表的长度:"+ infos.size());}break;// 手指触摸滑动case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:System.out.println("SCROLL_STATE_TOUCH_SCROLL");break;// 惯性滑行状态case OnScrollListener.SCROLL_STATE_FLING:System.out.println("SCROLL_STATE_FLING");break;default:break;}}/** *  * 滚动的时候调用的方法 *  */@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {}});

完整的代码如下:注意注释中提到的几个小细节:

package com.ustc.mobilemanager;import java.util.List;import android.app.Activity;import android.app.AlertDialog;import android.app.AlertDialog.Builder;import android.content.DialogInterface;import android.os.Bundle;import android.text.TextUtils;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.view.Window;import android.widget.AbsListView.OnScrollListener;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.AbsListView;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.CheckBox;import android.widget.EditText;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;import com.ustc.mobilemanager.db.BlackNumberDao;import com.ustc.mobilemanager.domain.BlackNumberInfo;public class CallSmsSaveActivity extends Activity {private ListView listView;private List<BlackNumberInfo> infos;private BlackNumberDao dao;private CallSmsSafeAdapter safeAdapter;private LinearLayout ll_loading;private int offset = 0;private int maxnumber = 20;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_call_sms_save);listView = (ListView) findViewById(R.id.list);ll_loading = (LinearLayout) findViewById(R.id.ll_loading);dao = new BlackNumberDao(this);final List<BlackNumberInfo> findAll = dao.findAll();//final int size = findAll.size();//System.out.println("size:" + size);fillData();// listview注册一个滚动事件的监听器listView.setOnScrollListener(new OnScrollListener() {/** * 当滚动的状态发生变化的时候 *  */@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {switch (scrollState) {// 空闲状态case OnScrollListener.SCROLL_STATE_IDLE:System.out.println("SCROLL_STATE_IDLE");// 判断当前listview滚动的位置// 获取ListView最后一个可见条目在集合里面的位置int lastVisiblePosition = listView.getLastVisiblePosition();System.out.println(lastVisiblePosition);if (lastVisiblePosition == (infos.size() - 1)) {System.out.println("列表被移动到了最后一个位置,加载更多数据。。。");offset += maxnumber;if (offset >= findAll.size()) {Toast.makeText(getApplicationContext(), "亲,数据已经加载完毕啦!", 0).show();ll_loading.setVisibility(View.INVISIBLE);}else {fillData();}//System.out.println("offset:" + offset);//System.out.println("列表的长度:"+ infos.size());}break;// 手指触摸滑动case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:System.out.println("SCROLL_STATE_TOUCH_SCROLL");break;// 惯性滑行状态case OnScrollListener.SCROLL_STATE_FLING:System.out.println("SCROLL_STATE_FLING");break;default:break;}}/** *  * 滚动的时候调用的方法 *  */@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {}});// 更新的方法(没有做好)// listView.setOnItemClickListener(new OnItemClickListener() {//// @Override// public void onItemClick(AdapterView<?> parent, View view,// final int position, long id) {// AlertDialog.Builder builder = new Builder(// CallSmsSaveActivity.this);// final AlertDialog dialog = builder.create();//// view = View.inflate(CallSmsSaveActivity.this,// R.layout.dialog_add_blacknumber, null);//// cancel = (Button) view.findViewById(R.id.cancel);// ok = (Button) view.findViewById(R.id.ok);// cb_phone = (CheckBox) view.findViewById(R.id.cb_phone);// cb_sms = (CheckBox) view.findViewById(R.id.cb_sms);// et_blacknumber = (EditText) view// .findViewById(R.id.et_blacknumber);//// dialog.setView(view, 0, 0, 0, 0);//// dialog.show();//// cancel.setOnClickListener(new OnClickListener() {//// @Override// public void onClick(View v) {// dialog.dismiss();// }// });// ok.setOnClickListener(new OnClickListener() {//// @Override// public void onClick(View v) {// String blacknumber = infos.get(position).getNumber();// et_blacknumber.setText(blacknumber);// if (TextUtils.isEmpty(blacknumber)) {// Toast.makeText(getApplicationContext(),// "黑名单号码不能为空!", 0).show();// return;// }// String mode;// if (cb_phone.isChecked() && cb_sms.isChecked()) {// // 全部拦截// mode = "3";//// } else if (cb_phone.isChecked()) {// // 电话拦截// mode = "1";//// } else if (cb_sms.isChecked()) {// // 短信拦截// mode = "2";// } else {//// Toast.makeText(getApplicationContext(), "请选择拦截模式!",// 0).show();// return;// }// // 数据被更新// dao.update(blacknumber, mode);// // 更新ListView的内容//// BlackNumberInfo info = new BlackNumberInfo();//// info.setMode(mode);//// info.setNumber(blacknumber);//// infos.add(0, info);//// // 通知适配器数据更新了//// safeAdapter.notifyDataSetChanged();//// dialog.dismiss();// }// });//// }// });}private void fillData() {List<BlackNumberInfo> all = dao.findAll();final int size = all.size();ll_loading.setVisibility(View.VISIBLE);new Thread() {public void run() {if (infos == null) {infos = dao.findPart(offset, maxnumber);}else {infos.addAll(dao.findPart(offset, maxnumber));}//这样写的问题?旧的数据还会存在吗?。。。所以加了上面的判断//infos = dao.findPart(offset, maxnumber);runOnUiThread(new Runnable() {@Overridepublic void run() {ll_loading.setVisibility(View.INVISIBLE);if (safeAdapter == null) {safeAdapter = new CallSmsSafeAdapter();listView.setAdapter(safeAdapter);}else {safeAdapter.notifyDataSetChanged();}//每次加载新的数据,旧的数据就会跑到第一页的第一个item,蛋疼//safeAdapter = new CallSmsSafeAdapter();//listView.setAdapter(safeAdapter);}});};}.start();}private class CallSmsSafeAdapter extends BaseAdapter {@Overridepublic int getCount() {return infos.size();}@Overridepublic View getView(final int position, View convertView,ViewGroup parent) {View view;ViewHolder viewHolder;if (convertView == null) {view = View.inflate(getApplicationContext(),R.layout.list_item_callsms, null);viewHolder = new ViewHolder();viewHolder.tv_black_number = (TextView) view.findViewById(R.id.tv_black_number);viewHolder.tv_black_mode = (TextView) view.findViewById(R.id.tv_black_mode);viewHolder.iv_delete = (ImageView) view.findViewById(R.id.iv_delete);view.setTag(viewHolder);} else {view = convertView;viewHolder = (ViewHolder) view.getTag();}viewHolder.tv_black_number.setText(infos.get(position).getNumber());String mode = infos.get(position).getMode();if ("1".equals(mode)) {viewHolder.tv_black_mode.setText("电话拦截");} else if ("2".equals(mode)) {viewHolder.tv_black_mode.setText("短信拦截");} else {viewHolder.tv_black_mode.setText("全部拦截");}// viewHolder.iv_delete.setTag(position);viewHolder.iv_delete.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {AlertDialog.Builder builder = new Builder(CallSmsSaveActivity.this);builder.setTitle("提示");builder.setMessage("确定删除这条记录吗?");builder.setPositiveButton("确定",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog,int which) {System.out.println("删除");// 删除数据库的内容dao.delete(infos.get(position).getNumber());// 更新界面infos.remove(position);safeAdapter.notifyDataSetChanged();}});builder.setNegativeButton("取消", null);builder.show();}});return view;}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}}static class ViewHolder {TextView tv_black_number;TextView tv_black_mode;ImageView iv_delete;}private EditText et_blacknumber;private CheckBox cb_phone, cb_sms;private Button cancel, ok;public void addBlackNumber(View view) {AlertDialog.Builder builder = new Builder(this);final AlertDialog dialog = builder.create();view = View.inflate(this, R.layout.dialog_add_blacknumber, null);cancel = (Button) view.findViewById(R.id.cancel);ok = (Button) view.findViewById(R.id.ok);cb_phone = (CheckBox) view.findViewById(R.id.cb_phone);cb_sms = (CheckBox) view.findViewById(R.id.cb_sms);et_blacknumber = (EditText) view.findViewById(R.id.et_blacknumber);dialog.setView(view, 0, 0, 0, 0);dialog.show();cancel.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {dialog.dismiss();}});ok.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {String blacknumber = et_blacknumber.getText().toString().trim();if (TextUtils.isEmpty(blacknumber)) {Toast.makeText(getApplicationContext(), "黑名单号码不能为空!", 0).show();return;}String mode;if (cb_phone.isChecked() && cb_sms.isChecked()) {// 全部拦截mode = "3";} else if (cb_phone.isChecked()) {// 电话拦截mode = "1";} else if (cb_sms.isChecked()) {// 短信拦截mode = "2";} else {Toast.makeText(getApplicationContext(), "请选择拦截模式!", 0).show();return;}// 数据被添加dao.add(blacknumber, mode);// 更新ListView的内容BlackNumberInfo info = new BlackNumberInfo();info.setMode(mode);info.setNumber(blacknumber);infos.add(0, info);// 通知适配器数据更新了safeAdapter.notifyDataSetChanged();dialog.dismiss();}});}}






0 0