现在的位置: 首页 > 综合 > 正文

黑名单之Listview的优化

2017年10月12日 ⁄ 综合 ⁄ 共 6133字 ⁄ 字号 评论关闭

listview的优化

1.复用历史缓存的view对象 converview
2.减少子孩子id查询的次数
3.分批的加载数据
4.分页的加载数据

优化的原则: 拆东墙补西墙。

1.时间换时间(listview的分批加载数据)

2.时间换空间  文件拷贝

3.空间换时间  文件快速查找的索引。 

4.空间换空间  虚拟内存  RAMdisk

代码思想:

1.在布局里面加一个 progressbar  体现客户需求

2.利用数据库查询分批加载查询数据,一次10条 然后添加一个滚动监听事件,滚动到最后 自动加载10条,显示progressbar  


3.


package com.itheima.mobilesafe;

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.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
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.itheima.mobilesafe.db.dao.BlackNumberDao;
import com.itheima.mobilesafe.domain.BlackNumberInfo;

public class CallSmsSafeActivity extends Activity {
	public static final String TAG = "CallSmsSafeActivity";
	private ListView lv_callsms_safe;
	//从数据库传过来的黑名单
	private List<BlackNumberInfo> infos;
	private BlackNumberDao dao;
	private CallSmsSafeAdapter adapter;
	private LinearLayout ll_loading;
	private int offset = 0;
	private int maxnumber = 20;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_call_sms_safe);
	ll_loading = (LinearLayout) findViewById(R.id.ll_loading);
	lv_callsms_safe = (ListView) findViewById(R.id.lv_callsms_safe);
	dao = new BlackNumberDao(this);
	fillData();

	// listview注册一个滚动事件的监听器。
	lv_callsms_safe.setOnScrollListener(new OnScrollListener() {
	// 当滚动的状态发生变化的时候。
	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
	switch (scrollState) {
	case OnScrollListener.SCROLL_STATE_IDLE:// 空闲状态
	// 判断当前listview滚动的位置
	// 获取最后一个可见条目在集合里面的位置。
	int lastposition = lv_callsms_safe.getLastVisiblePosition();

	// 集合里面有20个item 位置从0开始的 最后一个条目的位置 19
	if (lastposition == (infos.size() - 1)) {
	System.out.println("列表被移动到了最后一个位置,加载更多的数据。。。");
	offset += maxnumber;
	fillData();
	}

	break;
	case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:// 手指触摸滚动
	break;
	case OnScrollListener.SCROLL_STATE_FLING:// 惯性滑行状态
	break;
	}
	}

<span style="white-space:pre">	</span>// 滚动的时候调用的方法。
	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
	int visibleItemCount, int totalItemCount) {

			}
		});

	}

	private void fillData() {
		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));
				}
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
			ll_loading.setVisibility(View.INVISIBLE);
			if (adapter == null) {
			adapter = new CallSmsSafeAdapter();
			lv_callsms_safe.setAdapter(adapter);
						}else{
				adapter.notifyDataSetChanged();
						}
					}
				});
			};
		}.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 holder;
			// 1.减少内存中view对象创建的个数
			if (convertView == null) {
			Log.i(TAG, "创建新的view对象:" + position);
				// 把一个布局文件转化成 view对象。
		view = View.inflate(getApplicationContext(),
			R.layout.list_item_callsms, null);
			// 2.减少子孩子查询的次数 内存中对象的地址。
			holder = new ViewHolder();
			holder.tv_number = (TextView) view
			.findViewById(R.id.tv_black_number);
			holder.tv_mode = (TextView) view
			.findViewById(R.id.tv_block_mode);
			holder.iv_delete = (ImageView) view
			.findViewById(R.id.iv_delete);
		// 当孩子生出来的时候找到他们的引用,存放在记事本,放在父亲的口袋
		view.setTag(holder);
			} else {
	Log.i(TAG, "厨房有历史的view对象,复用历史缓存的view对象:" + position);
			view = convertView;
		holder = (ViewHolder) view.getTag();// 5%
			}
		holder.tv_number.setText(infos.get(position).getNumber());
			String mode = infos.get(position).getMode();
			if ("1".equals(mode)) {
				holder.tv_mode.setText("电话拦截");
			} else if ("2".equals(mode)) {
				holder.tv_mode.setText("短信拦截");
			} else {
				holder.tv_mode.setText("全部拦截");
			}
			holder.iv_delete.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					AlertDialog.Builder builder = new Builder(
							CallSmsSafeActivity.this);
					builder.setTitle("警告");
					builder.setMessage("确定要删除这条记录么?");
					builder.setPositiveButton("确定",
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									// 删除数据库的内容
									dao.delete(infos.get(position).getNumber());
									// 更新界面。
									infos.remove(position);
									// 通知listview数据适配器更新
									adapter.notifyDataSetChanged();
								}
							});
					builder.setNegativeButton("取消", null);
					builder.show();
				}
			});
			return view;
		}

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

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

	/**
	 * view对象的容器 记录孩子的内存地址。 相当于一个记事本
	 */
	static class ViewHolder {
		TextView tv_number;
		TextView tv_mode;
		ImageView iv_delete;
	}

	private EditText et_blacknumber;
	private CheckBox cb_phone;
	private CheckBox cb_sms;
	private Button bt_ok;
	private Button bt_cancel;

	public void addBlackNumber(View view) {
		AlertDialog.Builder builder = new Builder(this);
		final AlertDialog dialog = builder.create();
		View contentView = View.inflate(this, R.layout.dialog_add_blacknumber,
				null);
		et_blacknumber = (EditText) contentView
				.findViewById(R.id.et_blacknumber);
		cb_phone = (CheckBox) contentView.findViewById(R.id.cb_phone);
		cb_sms = (CheckBox) contentView.findViewById(R.id.cb_sms);
		bt_cancel = (Button) contentView.findViewById(R.id.cancel);
		bt_ok = (Button) contentView.findViewById(R.id.ok);
		dialog.setView(contentView, 0, 0, 0, 0);
		dialog.show();
		bt_cancel.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.dismiss();
			}
		});
		bt_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);
				// 通知listview数据适配器数据更新了。
				adapter.notifyDataSetChanged();
				dialog.dismiss();
			}
		});

	}
}

抱歉!评论已关闭.