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

分批加载数据是为了解决用户体验的问题,而分页加载是为了解决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() {
			/**
			 * 当滚动的状态发生变化的时候
			 * 
			 */
			@Override
			public 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;
				}
			}

			/**
			 * 
			 * 滚动的时候调用的方法
			 * 
			 */
			@Override
			public 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;

	@Override
	protected 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() {
			/**
			 * 当滚动的状态发生变化的时候
			 * 
			 */
			@Override
			public 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;
				}
			}

			/**
			 * 
			 * 滚动的时候调用的方法
			 * 
			 */
			@Override
			public 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() {

					@Override
					public 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 {

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

		@Override
		public 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() {
				@Override
				public void onClick(View v) {
					AlertDialog.Builder builder = new Builder(
							CallSmsSaveActivity.this);
					builder.setTitle("提示");
					builder.setMessage("确定删除这条记录吗?");
					builder.setPositiveButton("确定",
							new DialogInterface.OnClickListener() {

								@Override
								public 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;
		}

		@Override
		public Object getItem(int position) {
			return null;
		}

		@Override
		public 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() {

			@Override
			public void onClick(View v) {
				dialog.dismiss();
			}
		});
		ok.setOnClickListener(new OnClickListener() {

			@Override
			public 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();
			}
		});

	}

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值