手机卫士-04
手机卫士-04
课1
实现第二个功能,通讯卫士 该功能做黑名单的拦截(短信或电话或短信和电话) 在主页面mainActivity里的switch/case加上该功能相应方法
case 1:
Intent intent = new Intent(MainActivity.this,CallSafeActivity.class);
startActivity(intent);
break;
}
清单文件加上activity节点:CallSafeActivity.class
创建CallSafeActivity.class/CallSafeActivity.class的xml:activitycallsafe.xml activitycallsafe.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/startpage">
<TextView
style="@style/textview_title_style"
android:text="通讯卫士"
android:gravity="center"
android:textColor="#E2DED8"
/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="10"
>
<LinearLayout
android:id="@+id/ll_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
android:orientation="vertical"
android:gravity="center">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#E2DED8"
android:textSize="15sp"
android:text="玩命加载中..."
/>
</LinearLayout>
<!-- android:fastScrollEnabled="true" 设置快速滑动 -->
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/blacklist"
android:divider="@drawable/list_devider"
android:fastScrollEnabled="true"
></ListView>
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="1"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="上一页"
android:onClick="pre"
android:layout_marginRight="10sp"
android:background="@drawable/btn_selector"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下一页"
android:layout_marginRight="10sp"
android:onClick="next"
android:background="@drawable/btn_selector"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳转"
android:onClick="jump"
android:layout_marginRight="10sp"
android:background="@drawable/btn_selector"
/>
<EditText
android:id="@+id/et_page"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/faith_yee_textview_style"
android:layout_marginRight="10sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_page"
style="@style/faith_yee_textview_style"
android:text="xxx"
/>
</LinearLayout>
</LinearLayout>
activitycallsafe.xml嵌套ListView:itemcallsafe.xml ListView:itemcallsafe.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height=""wrap_content""
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/faith_yee_textview_style"
android:text="xxx"
android:id="@+id/tv_name"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/faith_yee_textview_style"
android:text="xxx"
android:textSize="18sp"
android:id="@+id/tv_phone"
android:layout_below="@id/tv_name"
/>
<ImageView
android:id="@+id/iv_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/delet_selector"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
/>
</RelativeLayout>
由于黑名单里的数据需要持久化,所以要存入到数据库中 新建数据库:BlackNumberDB.class
BlackNumberDBHelper.java
public class BlackNumberDBHelper extends SQLiteOpenHelper {
public BlackNumberDBHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, "callsafe.db", null, 1);
}
/**
* 创建blackinfo这个表
* number 黑名单电话号码
* mode 黑名单拦截的模式
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table blackinfo (_id integer primary key autoincrement,number varchar(20),mode varchar(2))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
初始化数据库、表 新建bean:BlackNumber(电话号码)
BlackNumberInfo.java
package com.itheima.phonesafeguard.bean;
public class BlackNumberInfo {
private String number;
private String mode;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
}
新建数据库的dao对象:BlackNumberDao.class
BlackNumberDao.java
public class BlackNumberDao {
private BlackNumberDBHelper helper;
public BlackNumberDao(Context context) {
super();
helper = new BlackNumberDBHelper(context);
}
/**
* 添加到黑名单数据库的方法
*
* @return
*/
public boolean add(String number, String mode) {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("number", number);
values.put("mode", mode);
long rowid = db.insert("blackinfo", null, values);
if (rowid == -1) {
return false;
} else {
return true;
}
}
/**
* 根据电话号码删除黑名单的数据
*
* @param number
* 电话号码
* @return
*/
public boolean delete(String number) {
SQLiteDatabase db = helper.getWritableDatabase();
int rowid = db.delete("blackinfo", "number = ?",
new String[] { number });
if (rowid == 0) {
return false;
} else {
return true;
}
}
/**
* 根据电话号码修改拦截的模式
*
* @return
*/
public boolean changeNumberMode(String number, String newmode) {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("mode", newmode);
int rowid = db.update("blackinfo", values, "number = ?",
new String[] { number });
if (rowid == 0) {
return false;
} else {
return true;
}
}
/**
* 根据电话号码查询拦截的模式
*
* @param number
* @return
*/
public String findNumberMode(String number) {
String mode = "0";
SQLiteDatabase db = helper.getReadableDatabase();
// 返回一个游标
Cursor cursor = db.query("blackinfo", new String[] { "mode" },
"number = ?", new String[] { number }, null, null, null);
// 判断当前的游标能否向后面移动
if (cursor.moveToNext()) {
mode = cursor.getString(0);
}
cursor.close();
db.close();
return mode;
}
/**
* 返回所有的黑名单
*
* @return
*/
public List<BlackNumberInfo> findAll() {
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db
.query("blackinfo", new String[] { "number", "mode" }, null,
null, null, null, null);
// 创建一个集合用来存放黑名单
List<BlackNumberInfo> lists = new ArrayList<BlackNumberInfo>();
while (cursor.moveToNext()) {
// 初始化黑名单的对象
BlackNumberInfo info = new BlackNumberInfo();
info.setNumber(cursor.getString(0));
info.setMode(cursor.getString(1));
lists.add(info);
}
SystemClock.sleep(2000);
cursor.close();
db.close();
return lists;
}
/**
* 分页加载数据
*
* @param pageSize
* 每一页展示的数据条目
* @param pageNumber
* 从哪一条数据开始
* @return 返回一个黑名单的集合数据
*/
public List<BlackNumberInfo> findPage(int pageSize, int pageNumber) {
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.rawQuery(
"select number,mode from blackinfo limit ? offset ?",
new String[] { String.valueOf(pageSize),
String.valueOf(pageSize * pageNumber) });
// 初始化黑名单的集合
ArrayList<BlackNumberInfo> lists = new ArrayList<BlackNumberInfo>();
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;
}
/**
* 返回所有数据的总数
*
* @return
*/
public int getCountTotal() {
String count = "";
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.rawQuery("select count(*) from blackinfo", null);
if (cursor.moveToNext()) {
count = cursor.getString(0);
}
cursor.close();
return Integer.parseInt(count);
}
}
在里面写增删查改的方法(添加黑名单方法、根据电话号码删除黑名单的数据、根据电话号码修改拦截的模式、根据电话号码查询拦截的模式、查询所有的方法(返回List)) 新建测试类TestBlackNumerDao.class测试一下dao对象
AndroidManifest.xml
<!-- 配置测试 -->
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.itheima.mobile47" />
<application
android:allowBackup="true"
android:icon="@drawable/main_icon"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<uses-library android:name="android.test.runner" />
TestBlackNumberDao.java
public class TestBlackNumberDao extends AndroidTestCase {
private Context context;
@Override
protected void setUp() throws Exception {
super.setUp();
context = getContext();
}
public void testAdd(){
BlackNumberDao dao = new BlackNumberDao(context);
for (int i = 10; i < 99; i++) {
String number = "138299610" + i +"";
dao.add(number, new Random().nextInt(3)+1+"");
}
}
public void testDelete(){
BlackNumberDao dao = new BlackNumberDao(context);
boolean result = dao.delete("13829961049");
assertEquals(true, result);
}
public void testfind(){
BlackNumberDao dao = new BlackNumberDao(context);
String mode = dao.findNumberMode("13829961066");
System.out.println(mode);
}
public void testfindall(){
BlackNumberDao dao = new BlackNumberDao(context);
List<BlackNumberInfo> lists = dao.findAll();
for (int i = 0; i < lists.size(); i++) {
System.out.println(lists.get(i).getMode()+"--------" + lists.get(i).getNumber());
}
}
}
新建一个工程,获取清单文件中需要的信息,复制到源工程下
课2
把数据都添加到listView里面:CallSafeActivity.class itemcallsafe.xml布局的实现(填充ListView的资源文件) 在itemcallsafe.xml的ImageView添加上选择器:delet_select.xml 在CallSafeActivity.class的getView中注入itemcallsafe.xml
考虑到黑名单里的仇人过多,查询量太大,所以可以把CallSafeActivity.class中的查询代码放在子线程中处理,并加上handler来处理
但是这样处理还是不够优化,我们还可以在getView里的convertView进行复用。这样查询出来的数据交给getView处理效率高多了
如果想在这里效率达到最高,可以加上private ViewHolder(){} 把在listView里要显示的小条目都放在ViewHolder里,然后修改getView里的代码:课下可以了解一下 当我们拖动listView是速度很慢,我们可以设置listView里的属性:fastScrollEnabled="true" 我们为打开功能时添加一个获取数据的时间响应动画“玩命加载中...” 给它线程睡一会,继续设计activitycallsafe.xml 加上,把其放在listView中,都用FrameLayout包住
但是考虑到我们如果通过查询数据是一次太多,不可能等一次过查完所有数据再显示到listView里,所以我们需要解决! 我们需要加载分页数据!
在activitycallsafe.xml里继续定义一个linearLayout(包裹上一页、下一页、跳转),我们需要渲染这个linearLayout,让其上面的布局不至于挤掉它,所以设置Weight 在CallSafeActivity.class里实现分页技术(实现上一页、下一页的功能)
课3
如果要使用分页技术,就不能使用之前dao提供的api(findAll)了 继续在dao里添加分页查询的api(findPage) 导出db文件,观察其两百条黑名单信息
sql:select number,mode form balckInfo limit 20 (从0开始到20)
sql:select number,mode form balckInfo limit 20 offset 20 (从20开始到40)
分页规律:20是pagesize:每一页展示的数据条目,40是pageNumber:从哪一条数据开始 findPage(String pageSize,String pageNumber)
代码如何实现:
继续在dao里提供一个api获取总的分页条目数(?/? 页码) getCountTotal 在CallSafeActivity.class实现业务逻辑:分页实现 取消线程里的findall方法,换成dao.findPage方法(测试一下) 然后继续实现上一页,下一页,跳转的按钮功能 下一页功能:public void next(View view),上一页功能 测试发现刷新界面那段代码有问题 实现跳转功能
CallSafeActivity.java
public class CallSafeActivity extends Activity {
private BlackNumberDao dao;
@ViewInject(R.id.ll_loading)
private LinearLayout ll_loading;
@ViewInject(R.id.tv_page)
private TextView tv_page;
@ViewInject(R.id.tv_mode)
private TextView tv_mode;
@ViewInject(R.id.tv_phone)
private TextView tv_phone;
@ViewInject(R.id.iv_delete)
private ImageView iv_delete;
@ViewInject(R.id.et_page)
private EditText et_page;
private ListView list_view;
private String number = "";
//自定义每页需要展示多少条数据
private int pageSize = 20;
private int totalpage;
private int mCurrentNumber = 0;
List<BlackNumberInfo> lists = new ArrayList<BlackNumberInfo>();
private CallSafeAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_call_safe);
list_view = (ListView) findViewById(R.id.blacklist);
ViewUtils.inject(this);
initData();
}
private void initData() {
//初始化dao对象
dao = new BlackNumberDao(this);
//设置当前的加载图片可见
ll_loading.setVisibility(View.VISIBLE);
totalpage = dao.getCountTotal()/ pageSize;
if(totalpage == 0){
totalpage = 1;
}
tv_page.setText(mCurrentNumber+1+"/"+totalpage+"页码");
//由于考虑到从数据库获得所有名单的操作太庞大,在加载页面的时候很耗时,所以使用子线程
new Thread(){
public void run(){
synchronized (CallSafeActivity.class) {
// lists = dao.findAll();
lists = dao.findPage(pageSize, mCurrentNumber);
System.out.println(lists);
try {
sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.sendEmptyMessage(0);
}
};
}.start();
}
Handler handler = new Handler(){
@Override
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
ll_loading.setVisibility(View.INVISIBLE);
if(lists!=null && lists.size()> 0 ){
adapter = new CallSafeAdapter();
list_view.setAdapter(adapter);
}
};
};
private class ViewHolder {
public TextView tv_phone;
public TextView tv_mode;
public ImageView iv_delete;
}
public class CallSafeAdapter extends BaseAdapter {
private ViewHolder holder;
@Override
public int getCount() {
return lists.size();
}
@Override
public Object getItem(int position) {
return lists.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if(convertView == null){
view = View.inflate(CallSafeActivity.this, R.layout.item_call_safe, null);
holder = new ViewHolder();
holder.tv_phone = (TextView) view.findViewById(R.id.tv_phone);
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();
}
holder.tv_phone.setText(lists.get(position).getNumber());
holder.iv_delete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(CallSafeActivity.this, "需要删除名单吗?", 0).show();
}
});
String mode = lists.get(position).getMode();
if(mode.equals("1")){
holder.tv_mode.setText("全部拦截");
}
if(mode.equals("2")){
holder.tv_mode.setText("短信拦截");
}
if(mode.equals("3")){
holder.tv_mode.setText("电话拦截");
}
return view;
}
}
/**
* 跳转到上一页
*
* @param view
*/
public void pre(View view){
if(mCurrentNumber <= 0 ){
Toast.makeText(CallSafeActivity.this, "已经是第一页了", 0).show();
return ;
}
mCurrentNumber--;
initData();
}
/**
* 跳转到下一页
*
* @param view
*/
public void next(View view){
System.out.println("xxxxxxxxxxxxxx-------------"+totalpage);
//totalpage=10
mCurrentNumber++;
if(mCurrentNumber >= totalpage ){
//重置会最后一页,以免点击上一页时再次搜索搜索一次最后一页的内容
mCurrentNumber=totalpage-1;
Toast.makeText(CallSafeActivity.this, "已经是最后一页了", 0).show();
return ;
}
System.out.println("------------------------>"+mCurrentNumber);
initData();
}
/**
* 跳转到哪一页
*
* @param view
*/
public void jump(View view) {
number = et_page.getText().toString().trim();
if(TextUtils.isEmpty(number)){
Toast.makeText(CallSafeActivity.this, "请输入页码", 0).show();
}else{
int number = Integer.parseInt(et_page.getText().toString().trim());
if(number <= 0 || number > totalpage){
return;
}else{
number--;
mCurrentNumber =number;
initData();
}
}
}
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。