手機衛士-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();
}
}
}
}