看板 KnucklesNote
作者 標題 [AndroidStudio] 使用資料庫 SQLite 儲存資料
時間 2016-01-27 Wed. 12:18:05
延續前一篇
[AndroidStudio] 使用 SearchView 過濾列表資料 - KnucklesNote板 - Disp BBS
在輸入要搜尋的看板前,ListView 是空的
可以在這邊先顯示之前瀏覽過的看板
搜尋框沒輸入時,顯示瀏覽過的看板
有輸入時,顯示搜尋結果
這邊我們要將瀏覽過的看板存在手機中,當APP關閉再打開時資料還會存在
要儲存簡單的 key-value 資料的話可以用 SharedPreferences
要儲存列表資料的話要用資料庫 SQLite
建立 SQLite 資料庫與資料表
先建立一個 SQLiteOpenHelper 類別
用來在APP剛安裝時,在手機上建立資料庫檔案
以及資料庫的結構改變時,更新手機上的資料庫檔案
新增一個 Java Class 檔,名稱輸入 DBHelper
修改 DBHelper.java
將類別 DBHelper 加上 extends SQLiteOpenHelper
依編輯器的提示加上成員函式 onCreate() 和 onUpgrade()
以及建構子 DBHelper()
然後改成像這樣
public class DBHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "mydata.db"; // 資料庫檔案名稱
private static final int DB_VERSION = 1; // 資料庫版本,資料結構改變的時候要加1
//建構子
public DBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
final String sql = "CREATE TABLE IF NOT EXISTS boardHistory "
+ "( bi INTEGER PRIMARY KEY, name VARCHAR(20) NOT NULL, title VARCHAR(50),"
+ " timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP )";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS boardHistory");
onCreate(db);
}
}
private static final String DB_NAME = "mydata.db"; // 資料庫檔案名稱
private static final int DB_VERSION = 1; // 資料庫版本,資料結構改變的時候要加1
//建構子
public DBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
final String sql = "CREATE TABLE IF NOT EXISTS boardHistory "
+ "( bi INTEGER PRIMARY KEY, name VARCHAR(20) NOT NULL, title VARCHAR(50),"
+ " timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP )";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS boardHistory");
onCreate(db);
}
}
在建構子 DBHelper() 中輸入 DB_NAME 與 DB_VERSION 給繼承的 SQLiteOpenHelper
onCreate() 是當APP第一次安裝,在手機上尚未建立資料庫檔案時會執行
所以在這邊加上想要建立的資料表 boardHistory
有四個欄位 bi, name, title, timestamp
其中 timestamp 的預設值為新增資料的時間,要用來依時間排序
onUpgrade() 是當 DB_VERSION 有改變時會執行
這邊是直接把資料表砍掉再重新建立,所以儲存的資料會消失
存取資料表的內容
由於存取資料庫的語法有點繁瑣
所以這邊我們將存取資料表 boardHistory 的動作包裝成一個類別
新增一個 Java Class 檔,名稱輸入 boardHistoryDB
內容修改為
public class BoardHistoryDB {
private SQLiteDatabase db;
final String TABLE_NAME = "boardHistory"; //資料表的名稱
final int MAX_LENGTH = 20; //限制最多幾筆資料
//建構子
public BoardHistoryDB(Context context){
DBHelper dbHelper = new DBHelper(context);
db = dbHelper.getWritableDatabase();
}
//關閉資料庫
public void close(){
db.close();
}
//取得資料的筆數
public int getCount(){
int count = 0;
Cursor cursor = db.rawQuery("SELECT COUNT(bi) FROM " + TABLE_NAME, null);
if (cursor.moveToNext()) {
count = cursor.getInt(0);
}
cursor.close();
return count;
}
//新增一個瀏覽過的看板
public void add(int bi, String name, String title){
String where = "bi = " + bi;
Cursor cursor = db.query(TABLE_NAME, null, where, null, null, null, null);
if(cursor.moveToFirst()){ //若已有存過這個看板
db.delete(TABLE_NAME, where, null); //刪掉這筆記錄,後面再重加
}
cursor.close();
if(getCount()>=MAX_LENGTH){ //記錄的看板到達上限
String orderBy = "timestamp ASC";
cursor = db.query(TABLE_NAME, null, null, null, null, null, orderBy);
if(cursor.moveToFirst()){
int first_bi = cursor.getInt(0);
db.delete(TABLE_NAME, "bi = " + first_bi, null); //刪掉第一筆記錄
}
}
ContentValues values = new ContentValues();
values.put("bi", bi);
values.put("name", name);
values.put("title", title);
db.insert(TABLE_NAME, null, values);
}
//輸出瀏覽過的看板列表,依時間排序,由新到舊
public ArrayList<String> getArrayList(){
ArrayList<String> result = new ArrayList<>();
String orderBy = "timestamp DESC";
Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, orderBy);
while (cursor.moveToNext()) {
result.add(cursor.getString(1) + " " + cursor.getString(2));
}
cursor.close();
return result;
}
//清除所有資料
public void clear(){
db.delete(TABLE_NAME, null, null);
}
}
private SQLiteDatabase db;
final String TABLE_NAME = "boardHistory"; //資料表的名稱
final int MAX_LENGTH = 20; //限制最多幾筆資料
//建構子
public BoardHistoryDB(Context context){
DBHelper dbHelper = new DBHelper(context);
db = dbHelper.getWritableDatabase();
}
//關閉資料庫
public void close(){
db.close();
}
//取得資料的筆數
public int getCount(){
int count = 0;
Cursor cursor = db.rawQuery("SELECT COUNT(bi) FROM " + TABLE_NAME, null);
if (cursor.moveToNext()) {
count = cursor.getInt(0);
}
cursor.close();
return count;
}
//新增一個瀏覽過的看板
public void add(int bi, String name, String title){
String where = "bi = " + bi;
Cursor cursor = db.query(TABLE_NAME, null, where, null, null, null, null);
if(cursor.moveToFirst()){ //若已有存過這個看板
db.delete(TABLE_NAME, where, null); //刪掉這筆記錄,後面再重加
}
cursor.close();
if(getCount()>=MAX_LENGTH){ //記錄的看板到達上限
String orderBy = "timestamp ASC";
cursor = db.query(TABLE_NAME, null, null, null, null, null, orderBy);
if(cursor.moveToFirst()){
int first_bi = cursor.getInt(0);
db.delete(TABLE_NAME, "bi = " + first_bi, null); //刪掉第一筆記錄
}
}
ContentValues values = new ContentValues();
values.put("bi", bi);
values.put("name", name);
values.put("title", title);
db.insert(TABLE_NAME, null, values);
}
//輸出瀏覽過的看板列表,依時間排序,由新到舊
public ArrayList<String> getArrayList(){
ArrayList<String> result = new ArrayList<>();
String orderBy = "timestamp DESC";
Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, orderBy);
while (cursor.moveToNext()) {
result.add(cursor.getString(1) + " " + cursor.getString(2));
}
cursor.close();
return result;
}
//清除所有資料
public void clear(){
db.delete(TABLE_NAME, null, null);
}
}
使用方法
要加入一筆瀏覽過的看板
在進入看板頁面時,執行
BoardHistoryDB boardHistoryDB = new BoardHistoryDB(this);
boardHistoryDB.add(mBoardId,mBoardName,mBoardTitle);
boardHistoryDB.close();
boardHistoryDB.add(mBoardId,mBoardName,mBoardTitle);
boardHistoryDB.close();
要列出瀏覽過的看板
在搜尋看板頁,新增成員變數
ArrayList<String> mHistoryList;
ArrayAdapter mHistoryAdapter;
多建立一個用來顯示瀏覽過看板的 Adapter ArrayAdapter mHistoryAdapter;
在 onCreate() 加入
BoardHistoryDB boardHistoryDB = new BoardHistoryDB(this);
mHistoryList = boardHistoryDB.getArrayList();
mHistoryAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mHistoryList);
mListView.setAdapter(mHistoryAdapter);
boardHistoryDB.close();
從資料庫中取出看板列表的 ArrayListmHistoryList = boardHistoryDB.getArrayList();
mHistoryAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mHistoryList);
mListView.setAdapter(mHistoryAdapter);
boardHistoryDB.close();
用這個 ArrayList 建立 mHistoryAdapter
將 mHistoryAdapter 掛上 ListView
在 onQueryTextChange() 裡
將原本用來清空 ListView 的 mListView.setAdapter(null); 改為
mListView.setAdapter(mHistoryAdapter);
因為建立了兩組 Adapter當搜尋框有值時,ListView 掛上搜尋結果的 Adapter
當搜尋框裡沒有值時,改成掛瀏覽過的看板的 Adapter
用程式修改 HeaderView 裡的文字
列表上方的 HeaderView 在xml的設定是顯示「搜尋結果」
要在搜尋框沒有值時,用程式將文字改為「瀏覽過的看板」
在 /res/values/strings.xml 加上
<string name="boardHistoryHeader">瀏覽過的看板</string>
在類別程式檔,加上成員變數
TextView mHeaderTextView;
在 mListView.addHeaderView(headerView); 下一行加上
mHeaderTextView = (TextView) findViewById(R.id.header_boardsearch);
在成員函式 onQueryTextChange() 裡
當搜尋框有值時,執行
mHeaderTextView.setText(R.string.boardSearchHeader);
當搜尋框沒有值時,執行 mHeaderTextView.setText(R.string.boardHistoryHeader);
重整列表與清除瀏覽記錄
參考這篇 [AndroidStudio] Toolbar 使用方法 - KnucklesNote板 - Disp BBS
在右上角加上重整列表與清除瀏覽記錄的按鈕
修改 menu_boardsearch.xml 的item為
<item
android:id="@+id/action_refresh"
android:icon="@drawable/ic_refresh_white_48dp"
android:title="refresh"
app:showAsAction="ifRoom"/>
<!-- 一律顯示在選單裡-->
<item
android:id="@+id/action_clear"
android:orderInCategory="100"
android:title="清除瀏覽記錄"
app:showAsAction="never" />
android:id="@+id/action_refresh"
android:icon="@drawable/ic_refresh_white_48dp"
android:title="refresh"
app:showAsAction="ifRoom"/>
<!-- 一律顯示在選單裡-->
<item
android:id="@+id/action_clear"
android:orderInCategory="100"
android:title="清除瀏覽記錄"
app:showAsAction="never" />
在頁面類別加上成員函式 refresh()
private void refresh(){
BoardHistoryDB boardHistoryDB = new BoardHistoryDB(this);
mHistoryList.clear();
mHistoryList.addAll(boardHistoryDB.getArrayList());
mHistoryAdapter.notifyDataSetChanged();
boardHistoryDB.close();
}
清空 mHistoryList 後,再從資料庫重抓資料放進來BoardHistoryDB boardHistoryDB = new BoardHistoryDB(this);
mHistoryList.clear();
mHistoryList.addAll(boardHistoryDB.getArrayList());
mHistoryAdapter.notifyDataSetChanged();
boardHistoryDB.close();
}
修改成員函式 onOptionsItemSelected()
加上點擊了右上角選單按鈕後的動作
case R.id.action_refresh: //點了重新整理
refresh();
return true;
case R.id.action_clear: //點了清除瀏覽過的看板
BoardHistoryDB boardHistoryDB = new BoardHistoryDB(this);
boardHistoryDB.clear();
boardHistoryDB.close();
mHistoryAdapter.clear();
return true;
refresh();
return true;
case R.id.action_clear: //點了清除瀏覽過的看板
BoardHistoryDB boardHistoryDB = new BoardHistoryDB(this);
boardHistoryDB.clear();
boardHistoryDB.close();
mHistoryAdapter.clear();
return true;
參考:
http://sweeteason.pixnet.net/blog/post/37364146-android-使用-sqlite-資料庫的方法
http://www.codedata.com.tw/mobile/android-tutorial-the-3rd-class-3-sqlite
--
※ 作者: Knuckles 時間: 2016-01-27 12:18:05
※ 編輯: Knuckles 時間: 2016-01-29 17:47:20
※ 看板: KnucklesNote 文章推薦值: 0 目前人氣: 0 累積人氣: 1096
回列表(←)
分享