listview的优化
1.复用历史缓存的view对象 converview
2.减少子孩子id查询的次数
3.分批的加载数据
4.分页的加载数据
优化的原则: 拆东墙补西墙。
1.时间换时间(listview的分批加载数据)
2.时间换空间 文件拷贝
3.空间换时间 文件快速查找的索引。
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();
}
});
}
}