顯示廣告
隱藏 ✕
看板 KnucklesNote
作者 Knuckles (站長 那克斯)
標題 [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);
    }
}

在建構子 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); 
    }
}


使用方法

要加入一筆瀏覽過的看板
在進入看板頁面時,執行
        BoardHistoryDB boardHistoryDB = new BoardHistoryDB(this);
        boardHistoryDB.add(mBoardId,mBoardName,mBoardTitle);
        boardHistoryDB.close();

要列出瀏覽過的看板

在搜尋看板頁,新增成員變數
    ArrayList<String> mHistoryList;
    ArrayAdapter mHistoryAdapter;
多建立一個用來顯示瀏覽過看板的 Adapter

在 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();
從資料庫中取出看板列表的 ArrayList
用這個 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" />

在頁面類別加上成員函式 refresh()
    private void refresh(){
        BoardHistoryDB boardHistoryDB = new BoardHistoryDB(this);
        mHistoryList.clear();
        mHistoryList.addAll(boardHistoryDB.getArrayList());
        mHistoryAdapter.notifyDataSetChanged();
        boardHistoryDB.close();
    }
清空 mHistoryList 後,再從資料庫重抓資料放進來

修改成員函式 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;



參考:
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 
分享網址: 複製 已複製
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇