模仿网易新闻下拉加载分页数据listView
在activtiycallsafe.xml里重新修改(去掉原来的button)
activtiycallsafe.xml
在CallSafeActivity.class里重新修改
list_view.setOnScrollListener//初始化listview的滚动监听 在方法里有分别识别(惯性滑动、当滚动然后停下来闲置的时候、在触摸屏幕的时候调用方法)的操作 现在目的是下拉滑动的数据到20条截止就再请求数据库获取数据 在case OnScrollListener.SCROLLSTATEIDLE里进行操作
CallSafeActivity.class
list_view.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
// 惯性滑动
case OnScrollListener.SCROLL_STATE_FLING:
break;
// 当滚动然后停下来闲置的时候
case OnScrollListener.SCROLL_STATE_IDLE:
// 最后一个显示可见的位置
int lastVisiblePosition = list_view
.getLastVisiblePosition();
System.out.println("lastVisiblePosition----->"
+ lastVisiblePosition);
if (lastVisiblePosition == lists.size() - 1) {
startIndex += pageCount;
if (startIndex > countTotal) {
Toast.makeText(CallSafeActivity.this,
"没有更多的数据进行加载了", 0).show();
return;
}
}
initData();
break;
// 在触摸屏幕的时候调用的方法
case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
在BlackNumberDao里继续加功能(分批加载数据)
CallSafeActivity.class里使用分批加载数据的方法(首先定义好startIndex、pageCount初始化了)
CallSafeActivity.class
/**
* 从第0条数据进行加载
*/
private int startIndex = 0;
/**
* 每页最多的加载数据
*/
private int pageCount = 20;
调用lists = dao.findPage2()
BlackNumberDao.java
/**
* 分批加载数据
*
* @param startIndex
* 开始数据的条目
* @param pageCount
* 每页最多加载多少条数据
* @return 返回一个黑名单的集合数据
*/
public List findPage2(int startIndex, int pageCount) {
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.rawQuery(
"select number,mode from blackinfo order by _id desc limit ? offset ?",
new String[] { String.valueOf(pageCount),
String.valueOf(startIndex) });
// 初始化黑名单的集合
ArrayList lists = new ArrayList();
while (cursor.moveToNext()) {
BlackNumberInfo info = new BlackNumberInfo();
info.setMode(cursor.getString(1));
info.setNumber(cursor.getString(0));
lists.add(info);
}
cursor.close();
db.close();
return lists;
}
但是这样做加载后就把之前的给覆盖了 解决小bug,在使用lists = dao.findPage2()的时候加个判断,如果lists!=null,就再lists里追加加载后的数据。
CallSafeActivity.class
// 当滚动然后停下来闲置的时候
case OnScrollListener.SCROLL_STATE_IDLE:
// 最后一个显示可见的位置
int lastVisiblePosition = list_view
.getLastVisiblePosition();
System.out.println("lastVisiblePosition----->"
+ lastVisiblePosition);
if (lastVisiblePosition == lists.size() - 1) {
startIndex += pageCount;
if (startIndex > countTotal) {
Toast.makeText(CallSafeActivity.this,
"没有更多的数据进行加载了", 0).show();
return;
}
}
initData();
break;
继续解决小bug,由于每次都追加后都new一个新的adapter,所以在new一个适配器时需要进行判断,如果已经有适配器时,就使用刷新界面的适配器方法notifyDataSetChanged
CallSafeActivity.class
//判断当前的结果值是否添加成功
boolean result = dao.add(phone, mode);
if(result){
if(adapter == null){
CallSafeAdapter adapter = new CallSafeAdapter(CallSafeActivity.this, lists);
list_view.setAdapter(adapter);
}else{
adapter.notifyDataSetChanged();
}
}
继续实现黑名单里的删除图片的删除功能 在getView里添加图片控件,并让holder去管理
itemcallsafe.xml
holder用来管理ListView里的GetView所绑定的xml文件里的控件 简单来说就是通过在下面 private class ViewHolder { TextView tvnumber; TextView tvmode; ImageView iv_delete; } ViewHolder里管理的控件变量,当在获取getView要绑定的xml资源到View view时,通过在绑定后把holder里管理的变量通过该view去findViewById获取对象并添加一个标记view.setTag(holder);,那么每次getView时就可以实现不用重复再重复的去findViewById获取对象,这就可以节省手机的cpu处理资源,大大减低ListView的效率
在设置的点击事件里进行操作集合移除的操作
但是如果不使用adapter的刷新方法,那么也看不出马上被删除的效果,解决这个小bug
CallSafeActivity.class
private class ViewHolder {
TextView tv_number;
TextView tv_mode;
ImageView iv_delete;
}
private class CallSafeAdapter extends
MyBaseAdapter {
private View view;
private ViewHolder holder;
//private BlackNumberInfo info;
public CallSafeAdapter(CallSafeActivity callSafeActivity,
List lists) {
super(lists, callSafeActivity);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
view = View.inflate(context, R.layout.item_call_safe, null);
holder = new ViewHolder();
holder.tv_number = (TextView) view.findViewById(R.id.tv_number);
holder.tv_mode = (TextView) view.findViewById(R.id.tv_mode);
holder.iv_delete = (ImageView) view.findViewById(R.id.iv_delete);
// 添加一个标记
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder) view.getTag();
}
final BlackNumberInfo info = lists.get(position);
System.out.println("---------------------"+info.getNumber());
//给imageview设置删除点击事件
holder.iv_delete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String blackNumber = info.getNumber();
//删除黑名单电话号码
boolean result = dao.delete(blackNumber);
//从集合里面移除黑名单电话号码
lists.remove(info);
if(result){
adapter.notifyDataSetChanged();
}
}
});
继续在黑名单里加上添加黑名单按钮的功能 在activitycallsafe.xml增加按钮控件
activitycallsafe.xml
在CallSafeActivity.java里为按钮方法添加一个对话框
CallSafeActivity.java
/**
* 添加黑名单电话号码
* @param view
*/
public void addBlackNumber(View view){
AlertDialog.Builder builder = new Builder(this);
View dialogview = View.inflate(CallSafeActivity.this, R.layout.dialog_add_black_number, null);
final EditText et_phone = (EditText) dialogview.findViewById(R.id.et_phone);
final CheckBox cb_phone = (CheckBox) dialogview.findViewById(R.id.cb_phone);
final CheckBox cb_sms = (CheckBox) dialogview.findViewById(R.id.cb_sms);
//取消
dialogview.findViewById(R.id.bt_cancel).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
dialog.dismiss();
}
});
//确定
dialogview.findViewById(R.id.bt_ok).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String mode = "0";
String phone = et_phone.getText().toString().trim();
//判断当前的电话号码是否有值
if(TextUtils.isEmpty(phone)){
Toast.makeText(CallSafeActivity.this, "请输入电话号码", 0).show();
return ;
}
/**
* 拦截模式 1 全部拦截 2 短信拦截 3 电话拦截
*/
if(cb_phone.isChecked() && cb_sms.isChecked()){
mode = "1";
}else if(cb_phone.isChecked()){
mode = "3";
}else if(cb_sms.isChecked()){
mode = "2";
}else{
Toast.makeText(CallSafeActivity.this, "请勾选拦截模式", 0).show();
return;
}
BlackNumberInfo info = new BlackNumberInfo();
info.setMode(mode);
info.setNumber(phone);
lists.add(0,info);
//判断当前的结果值是否添加成功
boolean result = dao.add(phone, mode);
if(result){
if(adapter == null){
CallSafeAdapter adapter = new CallSafeAdapter(CallSafeActivity.this, lists);
list_view.setAdapter(adapter);
}else{
adapter.notifyDataSetChanged();
}
}
dialog.dismiss();
}
});
builder.setView(dialogview);
dialog = builder.show();
}
实现对话框的布局dialogaddblack_number.xml
dialogaddblack_number.xml
设计完毕后就继续注入dialogView去使用。
CallSafeActivity.java
AlertDialog.Builder builder = new Builder(this);
View dialogview = View.inflate(CallSafeActivity.this, R.layout.dialog_add_black_number, null);
final EditText et_phone = (EditText) dialogview.findViewById(R.id.et_phone);
final CheckBox cb_phone = (CheckBox) dialogview.findViewById(R.id.cb_phone);
final CheckBox cb_sms = (CheckBox) dialogview.findViewById(R.id.cb_sms);
(技巧)我们可以设置dialog里面的一个方法setCanceledOnTouchOutside(true);的一个方法去锁定提示框
AlertDialog dialog = builder.show();
dialog.setCanceledOnTouchOutside(true);
主要逻辑是对话框里的确定按钮响应事件
1、拿到EditText里的内容
2、判断checkBox是否有勾上
3、操作赋值
4、更新适配器
CallSafeActivity.java
//确定
dialogview.findViewById(R.id.bt_ok).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String mode = "0";
String phone = et_phone.getText().toString().trim();
//判断当前的电话号码是否有值
if(TextUtils.isEmpty(phone)){
Toast.makeText(CallSafeActivity.this, "请输入电话号码", 0).show();
return ;
}
/**
* 拦截模式 1 全部拦截 2 短信拦截 3 电话拦截
*/
if(cb_phone.isChecked() && cb_sms.isChecked()){
mode = "1";
}else if(cb_phone.isChecked()){
mode = "3";
}else if(cb_sms.isChecked()){
mode = "2";
}else{
Toast.makeText(CallSafeActivity.this, "请勾选拦截模式", 0).show();
return;
}
BlackNumberInfo info = new BlackNumberInfo();
info.setMode(mode);
info.setNumber(phone);
lists.add(0,info);
//判断当前的结果值是否添加成功
boolean result = dao.add(phone, mode);
if(result){
if(adapter == null){
CallSafeAdapter adapter = new CallSafeAdapter(CallSafeActivity.this, lists);
list_view.setAdapter(adapter);
}else{
adapter.notifyDataSetChanged();
}
}
dialog.dismiss();
}
});
bug,如果添加的话,它会加载到lists的最后,解决lists.add(position,xxx); 解决了上一个bug之后,发现关掉该页面后再打开,lists还是按顺序展示,所以我们需要修改dao层里的数据库的sql
BlackNumberDao.java
public List findPage2(int startIndex, int pageCount) {
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.rawQuery(
"select number,mode from blackinfo order by _id desc limit ? offset ?",
new String[] { String.valueOf(pageCount),
String.valueOf(startIndex) });
真正实现电话和信息拦截的功能 首先实现电话拦截 短信拦截:在清单文件里已经实现过了(静态注册过了) 今天实现短信拦截的动态注册
在之前学过activitysettingcenter.xml里添加二维码的布局
activitysettingcenter.xml
二维码实现 颜色选择器添加:在value里新建color.xml--->然后在新建的listselector.xml来调用,然后再在关于的TextView里调用 activityabount.xml--->ImageView 里加上一个网上下载的二维码图片在abountActivity.class注入,然后通过SettingCenterActivity.java里的关于(点击时加上选择器)跳到abountActivity.class里 并在SettingCenterActivity.java里实现二维码功能--->调到处理二维码的类:abountActivity.class
AboutActivity.java
public class AboutActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
}
}
清单文件加上activity节点
布置布局文件activity_abount.xml--->ImageView
activity_about.xml
继续在xx实现扫一扫的功能 zxing的githut里下载二维码的开源代码 移植到项目中 然后通过顺藤摸瓜去找到项目如何把链接显示在照片上,然后找到首页面,首页面所支持的TextView,然后在TextView要setText时找到大致的地方去截取要set的地址值,然后进行处理
继续在activitysettingcenter.xml设置中心布局里实现黑名单拦截功能打开
在SettingCenterActivity.java里加上响应事件里增加功能 使用服务实现功能 新建黑名单拦截服务:CallSafeService.java
四大组件配置清单文件(服务)
true:开启服务、false:关闭服务,在手机本地的应用服务里查看没加功能的服务开启没
SettingCenterActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting_center);
intent = new Intent(this,CallSafeService.class);
//黑名单设置
setting_view_black.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(setting_view_black.isChecked()){
setting_view_black.setChecked(false);
stopService(intent);
}else{
setting_view_black.setChecked(true);
startService(intent);
}
}
});
继续实现服务功能CallSafeService.java 过滤器是广播的一种实现receiver节点里的action节点 在CallSafeService.java动态注册短信的广播,然后在filter里设置setPriority,在然后就registerReceiver
CallSafeService.java
public class CallSafeService extends Service {
private BlackNumberDao dao;
private TelephonyManager tm;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
// 获取到黑名单的数据
dao = new BlackNumberDao(this);
// 获取到电话相关的服务
tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
// 初始化电话状态的监听
MyPhoneStateListener listener = new MyPhoneStateListener();
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
// 初始化内部拦截短信的广播
InnerSmsReceiver receiver = new InnerSmsReceiver();
// 初始化一个短信拦截的action
IntentFilter filter = new IntentFilter(
"android.provider.Telephony.SMS_RECEIVED");
filter.setPriority(Integer.MAX_VALUE);
// 注册短信的广播
registerReceiver(receiver, filter);
}
在内部类InnerSmsReceiver实现短信拦截的功能
CallSafeService.java
private class InnerSmsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 获取到短信
Object[] objs = (Object[]) intent.getExtras().get("pdus");
for (Object obj : objs) {
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) obj);
// 获取到短信的电话号码
String number = smsMessage.getOriginatingAddress();
// 获取到短信的内容
String body = smsMessage.getMessageBody();
// 获取到拦截模式
String mode = dao.findNumberMode(number);
// 如果是全部拦截或者是短信拦截。那么就全部拦截下来
if (mode.equals("1") || mode.equals("2")) {
System.out.println("拦截下来了");
abortBroadcast();
}
// 智能拦截
if (body.contains("fapiao")) {
System.out.println("垃圾短信拦截下来了");
abortBroadcast();
}
}
}
}
在onCreate里操作dao通过电话号码获取拦截模式,然后给内部类
String mode = dao.findNumberMode(number);
// 如果是全部拦截或者是短信拦截。那么就全部拦截下来
if (mode.equals("1") || mode.equals("2")) {
System.out.println("拦截下来了");
abortBroadcast();
}
InnerSmsReceiver实现短信拦截的功能abortBroadcast(),我们可以把短信服务理解为一个有序广播,然后我们通过条件定位到手机号,当服务一促发就查询dao,当对比有该号码就拦截abortBroadcast()。 该服务打开时继续设置一个方法拦截一些垃圾短信,只要短信body包含了一些我们自己我想见到信息内容,就abortBroadcast(),上下文的方法
继续在CallSafeService实现电话号码拦截
使用getSystemService(TelephonyManager)获得电话服务,然后继续实现,这是之前学习服务时候学习过的电话窃听的一个例子 在电话不同的状态下进行拦截操作。(在手机铃响时就使用dao查询拦截的模式,从而进行分类拦截)
继续实现拦截短信中结束电话的方法(在TelephonyManager查看源码):CallSafeService.class TelephonyManager里的getService是关于服务的知识,回忆起老师当时的调用远程服务的例子 挂掉电话的方法(观察源码后想到的方法) endcall()://使用反射的方法获得类 然后再获取方法,然后获取到ibunder远程服务(getService) 把远程服务的aidl拿过来 放在和该aidl一样的包名里(打开aidl里查看包名) 最后调用远程服务,把ibunder传进去,最后调用endcall()系统远程服务来挂断电话 课下回忆老师教我们远程服务的实例对比今天的课的内容 解决小bug,在设置中心关闭服务,但是后台服务却没有关,如何控制呢?把开关标记存在sp不合适,因为在应用设置处清除数据后sp没了,但是服务却依然在跑。 新建类ServiceIsRunning.java,该util类用来判断服务是否开启、 使用ActivityManager来判断正在运行的一些服务am.getRunningServices(50) 把传进来的服务名字和系统获得的服务名字做对比,如果名字相同,就进行关闭操作,然后设置中心SettingCenterActivity.class就使用该工具类来进行开关服务操作onstart();
CallSafeService.java
@Override public void onCreate() {
// TODO Auto-generated method stub super.onCreate(); // 获取到黑名单的数据 dao = new BlackNumberDao(this);
// 获取到电话相关的服务
tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
// 初始化电话状态的监听
MyPhoneStateListener listener = new MyPhoneStateListener();
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
// 初始化内部拦截短信的广播
InnerSmsReceiver receiver = new InnerSmsReceiver();
// 初始化一个短信拦截的action
IntentFilter filter = new IntentFilter(
"android.provider.Telephony.SMS_RECEIVED");
filter.setPriority(Integer.MAX_VALUE);
// 注册短信的广播
registerReceiver(receiver, filter);
}
private class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
// 闲置状态
case TelephonyManager.CALL_STATE_IDLE:
break;
// 响铃状态
case TelephonyManager.CALL_STATE_RINGING:
String mode = dao.findNumberMode(incomingNumber);
if(mode.equals("1")||mode.equals("3")){
System.out.println("电话拦截");
//挂断电话
endcall();
}
break;
// 通话状态
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}
/**
* 挂掉电话
*/
public void endcall() {
try {
//使用类加载器去加载一个类
Class> clazz = getClassLoader().loadClass("android.os.ServiceManager");
//获取到方法
/**
* 第一个参数是名字
* 第二个参数是类型
*/
Method method = clazz.getDeclaredMethod("getService", String.class);
//实现调用这个方法
//第一个参数:如果是静态的那么就是设置为null
IBinder iBinder = (IBinder) method.invoke(null, TELEPHONY_SERVICE);
//通过IBinder对象获取到ITelephony
ITelephony iTelephony = ITelephony.Stub.asInterface(iBinder);
//挂断电话
iTelephony.endCall();
} catch (Exception e) {
e.printStackTrace();
}
}
实现号码归属地查询 在高级工具里设计case 7 新建ToolsActivity.java 布局activity_tools.xml
activity_tools.xml
ToolsActivity.java
public class ToolsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tools);
}
/**
* 归属地查询
* @param view
*/
public void queryLocation(View view){
Intent intent = new Intent(this,QueryLocationActivity.class);
startActivity(intent);
}
}
回到ToolsActivity.java实现号码归属地查询:queryLocation--->方法跳到下一个号码归属地查询的Activity:新建QueryLocationActivity+布局文件activityquerylocation.xml
activityquerylocation.xml
QueryLocationActivity.java
public class QueryLocationActivity extends Activity {
@ViewInject(R.id.et_number)
private EditText et_number;
@ViewInject(R.id.tv_address)
private TextView tv_address;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_query_location);
ViewUtils.inject(this);
}
/**
* 点击查询归属地
*
* @param view
*/
public void btQuery(View view) {
String number = et_number.getText().toString().trim();
if(TextUtils.isEmpty(number)){
Toast.makeText(QueryLocationActivity.this, "请输入查询号码", 0).show();
}else{
LocationDao dao = new LocationDao();
String address = dao.getLocation(number);
tv_address.setText("地理位置号码归属地 : " +address);
}
}
}
实现点击查询归属地的功能btQuery(查询数据库) 观察金山手机卫士发现,清空该app的数据后,重新打开时会自动导入之前的数据库 因此我们也模拟该app的导入数据库模式导入,即在打开首页时就导入进来 先把数据库放入到assets目录下 在SplashActivity里加上拷贝数据库方法copyDB,用来初始化数据库 把asset里的文件流拷贝到data/data下 考虑到如果拷贝的数据比较大,所以使用子线程来作拷贝操作 这里使用线程池来执行线程操作
SplashActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// 设置没有标题 必须写到setcontview前面
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_splash);
ViewUtils.inject(this);
// ImageView image_view = (ImageView) findViewById(R.id.image_view);
// image_view.setBackgroundResource(R.drawable.ic_launcher);
// 获取到包的管理者。
PackageManager pm = getPackageManager();
try {
// 拷贝数据库到data/data目录下面
copyDB("address.db");
SplashActivity.java
/**
* 拷贝数据库
*
* @param dbName
* 数据库的名字
*/
private void copyDB(String dbName) {
ExecutorService executorService = Executors.newFixedThreadPool(1);
TaskRunnable taskRunnable = new TaskRunnable(dbName);
executorService.execute(taskRunnable);
}
private class TaskRunnable implements Runnable {
private String dbName = null;
public TaskRunnable(String dbName) {
this.dbName = dbName;
}
@Override
public void run() {
try {
InputStream is = getAssets().open(dbName);
// 获取到一个输出流.
// 第一个参数是数据库的名字。第二个参数是模式。设置是私有的
FileOutputStream fos = openFileOutput(dbName, 0);
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
is.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
继续实现号码归属地查询,QueryLocationActivity中的btQuery 在edittext里进行输入号码,然后进行与数据库查询比较 新建一个为号码归属地查询的dao--->getLocation(返回地理位置)
LocationDao.java
public class LocationDao {
/**
* 返回地理位置
*
* @param number
* 查询的电话号码
* @return
*/
public String getLocation(String number) {
String location = "";
// 获取到Database
// 第一个参数是数据库的路径,第二个参数是工厂默认不要。第三个参数是标记。设置只读
SQLiteDatabase db = SQLiteDatabase.openDatabase(
"/data/data/com.itheima.mobile47/files/address.db", null,
SQLiteDatabase.OPEN_READONLY);
Cursor cursor = db.rawQuery(
"select location from data2 where id =( select outkey from data1 where id = ?) ",
new String[] { number.substring(0, 7) });
if(cursor.moveToNext()){
location = cursor.getString(0);
}
return location;
}
}
(新技巧)在getLocation里获取数据库的代码是SQLiteDatabase db = SQLiteDatabase.openDatabase("/data/data/com.itheima.mobile47/files/address.db",null,SQLiteDatabase.READONLY); 拿到了db后,继续实现查询方法。需要做联表查询 1、select outkey from data1 where id = 1300020 得到id = 3 2、select location from data2 where id = 3 得到结果
课下对比一下以前使用数据库的方式和这节课的方式的方式的不同:
那是因为以前我们那样做是为了先创建一个数据库,而现在的是数据库已经存在,所以直接拿到数据库的对象
返回location 回到QueryLocationActivity.class,在btQuery里把location设置到控件TextView里
QueryLocationActivity.java
/**
* 点击查询归属地
*
* @param view
*/
public void btQuery(View view) {
String number = et_number.getText().toString().trim();
if(TextUtils.isEmpty(number)){
Toast.makeText(QueryLocationActivity.this, "请输入查询号码", 0).show();
}else{
LocationDao dao = new LocationDao();
String address = dao.getLocation(number);
tv_address.setText("地理位置号码归属地 : " +address);
}
}
如何让TextView实现可点击化:在该控件里加上focusable\clickable\enabled来实现
holder用来管理ListView里的GetView所绑定的xml文件里的控件 简单来说就是通过在下面 private class ViewHolder { TextView tvnumber; TextView tvmode; ImageView iv_delete; } ViewHolder里管理的控件变量,当在获取getView要绑定的xml资源到View view时,通过在绑定后把holder里管理的变量通过该view去findViewById获取对象并添加一个标记view.setTag(holder);,那么每次getView时就可以实现不用重复再重复的去findViewById获取对象,这就可以节省手机的cpu处理资源,大大减低ListView的效率
在设置的点击事件里进行操作集合移除的操作
但是如果不使用adapter的刷新方法,那么也看不出马上被删除的效果,解决这个小bug
CallSafeActivity.class
private class ViewHolder {
TextView tv_number;
TextView tv_mode;
ImageView iv_delete;
}
private class CallSafeAdapter extends MyBaseAdapter {
private View view;
private ViewHolder holder;
// private BlackNumberInfo info;
public CallSafeAdapter(CallSafeActivity callSafeActivity,
List lists) {
super(lists, callSafeActivity);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
view = View.inflate(context, R.layout.item_call_safe, null);
holder = new ViewHolder();
holder.tv_number = (TextView) view.findViewById(R.id.tv_number);
holder.tv_mode = (TextView) view.findViewById(R.id.tv_mode);
holder.iv_delete = (ImageView) view.findViewById(R.id.iv_delete);
// 添加一个标记
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder) view.getTag();
}
final BlackNumberInfo info = lists.get(position);
System.out.println("---------------------"+info.getNumber());
//给imageview设置删除点击事件
holder.iv_delete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String blackNumber = info.getNumber();
//删除黑名单电话号码
boolean result = dao.delete(blackNumber);
//从集合里面移除黑名单电话号码
lists.remove(info);
if(result){
adapter.notifyDataSetChanged();
}
}
});
listView里的适配器中数据刷新的技巧,为了节省cpu资源,不用每次显示listView时都要new出一个新的适配器
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
// 设置loading的图片不可以见
ll_loading.setVisibility(View.INVISIBLE);
if (lists != null && lists.size() > 0) {
//判断适配器里面是否有数据。第一次为null那么就需要创建一个适配器。
//为了防止每一次就重新新建适配器。那么就只需要刷新界面
if (adapter == null) {
adapter = new CallSafeAdapter(CallSafeActivity.this, lists);
list_view.setAdapter(adapter);
} else {
// 刷新界面
adapter.notifyDataSetChanged();
}
}
};
};
资料下载