書籤的功能已經完成了,那麼現在開始就是歷史的功能模塊。
因爲爲了方便於數據的管理,所以在原有的書籤管理的基礎上,進行了相應的修改,通過這個修改,可以使得我們能夠同時管理書籤和歷史。
自然還是數據管理的接口的修改:
package com.example.database;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public interface IDatabase {
/**
* 增加
* @param sqLiteDatabase 數據庫
* @param tableName 表
* @param name 名
* @param url 地址
* @param date 日期
* */
public boolean add(SQLiteDatabase sqLiteDatabase, String tableName,String name, String url,long date);
/**
* 刪除
* @param sqLiteDatabase 數據庫
* @param tableName 表
* @param id 書籤ID
* */
public boolean delete(SQLiteDatabase sqLiteDatabase, String tableName,String id);
/**
* 刪除所有
* @param sqLiteDatabase 數據庫
* @param tableName 表
* */
public boolean deleteAll(SQLiteDatabase sqLiteDatabase, StringtableName);
/**
* 修改
* @param sqLiteDatabase 數據庫
* @param tableName 表
* @param id 修改的ID
* @param name 修改後的名
* @param url 修改後的地址
* */
public boolean modify(SQLiteDatabase sqLiteDatabase, String tableName,String id, String name, String url);
/**
* 獲取所有
* @param sqLiteDatabase 數據庫
* @param tableName 表
* @return Cursor
* */
public Cursor getAll(SQLiteDatabase sqLiteDatabase, StringtableName);
/**
* 查詢某個書籤是否存在,即查詢url是否重複
* @param tableName 表
* @param sqLiteDatabase 數據庫
* @param url 地址
* */
public boolean multiply(SQLiteDatabase sqLiteDatabase, StringtableName, String url);
/**
* 開始事務
* @param readOnly是否只讀
* @param callback函數回調
* */
void transactionAround(boolean readOnly, CallBack callback);
}
代碼片段10.2.19 修改後的數據接口
注意,我們可以看到,我在這裏添加了一個String的參數,這個參數的形參名爲tableName,即是用來分別是對書籤還是歷史進行操作。
至於數據管理的實現,基本沒有什麼變更,將原本固定的數據表改爲變量tableName即可。不過,因爲數據的表示不一樣,歷史相對於書籤來說多了個字段就是日期,歷史可以通過這個日期來劃分組,不過現階段對這個不做處理。
@Override
public boolean add(SQLiteDatabase sqLiteDatabase, String tableName,String name, String url,long date) throws SQLException{
ContentValues values = new ContentValues();
values.put("name", name);
values.put("url", url);
if(tableName.equals(FavAndHisManager.TABEL_NAME_Favorite)){
Log.d(DEG_TAG,"name:"+name+",url:"+url);
}else{
values.put("date", date);
Log.d(DEG_TAG,"name:"+name+",url:"+url+",date:"+date);
}
long id = sqLiteDatabase.insert(tableName,null, values);
if(id!=-1){
return true;
}else{
return false;
}
}
//新增的方法,用來清空歷史
@Override
public boolean deleteAll(SQLiteDatabase sqLiteDatabase, StringtableName) {
Log.d(DEG_TAG,"deleteAll");
int number = sqLiteDatabase.delete(tableName,null, null);
Log.d(DEG_TAG,"deleteAll_result:"+number);
if(number!=0){
return true;
}else{
return false;
}
}
@Override
public Cursor getAll(SQLiteDatabase sqLiteDatabase, StringtableName) {
String[] returnColmuns = null;
if(tableName.equals(FavAndHisManager.TABEL_NAME_Favorite)){
returnColmuns = new String[]{
"id as_id",
"name",
"url"
};
}else{
returnColmuns = new String[]{
"id as_id",
"name",
"url",
"date"
};
}
Cursor result = sqLiteDatabase.query(tableName, returnColmuns,null, null,null, null,null);
while(result.moveToNext()){
String id = String.valueOf(result.getInt(result.getColumnIndex("_id")));
String name = result.getString(result.getColumnIndex("name"));
String url = result.getString(result.getColumnIndex("url"));
if(tableName.equals(FavAndHisManager.TABEL_NAME_Favorite)){
Log.d(DEG_TAG,"id:"+id+",name:"+name+",url:"+url);
}else{
String date = String.valueOf(result.getLong(result.getColumnIndex("date")));
Log.d(DEG_TAG,"id:"+id+",name:"+name+",url:"+url+",date:"+date);
}
}
return result;
}
代碼片段10.2.20 需要修改的方法
這裏的新增的方法有個清空歷史,因爲我們在操作瀏覽器的時候,往往會清空一些歷史數據,來釋放空間。
而修改的兩個方法前者是因爲插入的時候列不同需要處理,後者是因爲返回的時候歷史界面需要額外的有一個date日期列。
處理好了這個,該是處理歷史事務的時候了,其實也就是調用上述的數據管理。
/**
* 增加歷史
* @param name 歷史名
* @param url 歷史地址
* @param date 存放歷史時間
* */
public boolean addHistory(final String name,final String url, finallong date) {
flag = false;
this.database.transactionAround(false,new CallBack() {
@Override
public voiddoSomething(SQLiteDatabase sqLiteDatabase) {
//歷史可重複,不重複的爲id和date
flag = database.add(sqLiteDatabase, TABEL_NAME_History, name, url, date);
}
});
Log.d(DEG_TAG,"result:"+flag);
return flag;
}
/**
* 刪除歷史
* @param id 歷史ID
* */
public boolean deleteHistory(final String id) {
flag = false;
this.database.transactionAround(false,new CallBack() {
@Override
public void doSomething(SQLiteDatabase sqLiteDatabase) {
flag = database.delete(sqLiteDatabase, TABEL_NAME_History, id);
}
});
return flag;
}
/**
* 刪除所有歷史
* */
public boolean deleteAllHistory(){
flag = false;
this.database.transactionAround(false,new CallBack() {
@Override
public void doSomething(SQLiteDatabase sqLiteDatabase) {
flag = database.deleteAll(sqLiteDatabase, TABEL_NAME_History);
}
});
return flag;
}
/**
* 獲取所有歷史
* @return Cursor
* */
public Cursor getAllHistories() {
this.database.transactionAround(true,new CallBack() {
@Override
public void doSomething(SQLiteDatabase sqLiteDatabase) {
resultMap = database.getAll(sqLiteDatabase, TABEL_NAME_History);
}
});
return resultMap;
代碼片段10.2.21 新增加歷史的事務管理
因爲數據庫都是同一個,所以,我儘量將這個事務的管理整合到了書籤事務管理的類中,重新命名這個類爲FavAndHisManager。
歷史事務管理已經完成,現在就開始進行相關的頁面編輯。頁面的編輯跟書籤的沒啥區別,因爲我現在並沒有以時間進行劃分。我們可以先看看效果,也就是書籤的編輯效果,就是更改了字體的顯示。
圖10.2.8 編輯菜單長按預覽
至於頁面的ListView,這個跟書籤的ListView保持一致。所以我在這裏就不展示了。
下面是歷史的ListView的初始化數據的代碼:
/**
* 初始化ListView中History的數據
* */
@SuppressWarnings("deprecation")
private void initDataHistory() {
//獲取書籤管理
this.favAndHisManager =new FavAndHisManager(this);
this.favAndHisCursor =this.favAndHisManager.getAllHistories();
this.favAndHisAdapter =new
SimpleCursorAdapter(getApplicationContext(),
R.layout.list_item,this.favAndHisCursor,
new String[]{"_id","name","url","date"},
new int[]{R.id.item_id, R.id.item_name,R.id.item_url,R.id.item_date});
this.historyContent.setAdapter(this.favAndHisAdapter);
}
代碼片段10.2.22 歷史ListView的初始化
長按單擊事件基本與書籤的相同,只不過是佈局的不同以及取出來的組件不同:
itemLongClickedPopWindow = new ItemLongClickedPopWindow(FavAndHisActivity.this,
ItemLongClickedPopWindow.HISTORY_ITEM_POPUPWINDOW, 200, 200);
itemLongClickedPopWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.favandhis_activity));
itemLongClickedPopWindow.showAsDropDown(view, view.getWidth()/2,-view.getHeight()/2);
TextView deleteHistory = (TextView) itemLongClickedPopWindow.getView(R.id.item_longclicked_deleteHistory);
TextView deleteAllHistories = (TextView) itemLongClickedPopWindow.getView(R.id.item_longclicked_deleteAllHistories);
ItemClickedListener itemClickedListener = newItemClickedListener(view);
deleteHistory.setOnClickListener(itemClickedListener);
deleteAllHistories.setOnClickListener(itemClickedListener);
代碼片段10.2.23 popupwindow的歷史彈出菜單
單擊事件如下:
Intent intent = new Intent();
intent.putExtra("url",((TextView) arg1.findViewById(R.id.item_url)).getText().toString());
setResult(0, intent);
finish();
代碼片段10.2.24 ListView的條目單擊事件
可以看到這個跟書籤的條目單擊事件一模一樣。另外需要注意的是,如果我們沒有點擊任何單擊事件,而是直接返回,會發現出現NULLPOINTER的空指針錯誤,這個就是因爲沒有設置默認的返回碼的緣故。沒有任何的返回碼,自然在父Actiivty的onActivity的方法中接受返回碼的時候會報出異常。
解決這個問題也很簡單,我們只需要在onCreate函數中設置如下語句即可:
//添加默認返回值
setResult(-1);
代碼片段10.2.25 設置默認返回值
當然,還需要在接受返回值的那裏進行處理:
@Override
protected void onActivityResult(int requestCode,int resultCode, Intent data) {
switch (resultCode) {
case -1:
//不做任何處理
break;
case 0:
webHolder.loadUrl(data.getStringExtra("url"));
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
這樣空指針的錯誤就解決了。
那麼還有一個最重要的問題,在什麼時候記錄歷史呢?我認爲,在每個頁面加載完成的時候,就可以將這次訪問加入,但因爲是歷史記錄的關係,並不需要進行重複性判斷(也許需要根據時間來判斷,相同的時間前提下不能進行重複添加,不過這個暫時不進行考慮)。
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
webUrlLayoutInput.setVisibility(View.GONE);
webUrlLayoutShow.setVisibility(View.GONE);
inputShow = false;
webUrlStr.setText(url);
changeStatueOfWebToolsButton();
//添加歷史
String date = new SimpleDateFormat("yyyyMMdd", Locale.CHINA).format(newDate()).toString();
favAndHisManager.addHistory(title, url, Long.parseLong(date));
}
代碼片段10.2.27 添加歷史記錄在每次訪問後
至此,歷史的功能完成。
案例: