Anko-SQLite的使用

Anko是Kotlin庫,可以使Android應(yīng)用程序的開發(fā)變得更快,更輕松。它使您的代碼干凈且易于閱讀,并且使您無需理會(huì)Android SDK for Java的粗糙之處。

Anko提供了許多擴(kuò)展功能
github地址:https://github.com/Kotlin/anko
根據(jù)github上的內(nèi)容引入到項(xiàng)目,這里貼出來的話以后肯定不是Anko最新版本了。

Anko的功能非常豐富,本文主要使用其為了簡(jiǎn)化SQLite的使用提供的數(shù)據(jù)庫管理的功能Anko-SQLite
以下為使用方法,主要參考:https://github.com/Kotlin/anko/wiki/Anko-SQLite

一 為你的項(xiàng)目創(chuàng)建數(shù)據(jù)庫管理工具類

class MyDatabaseOpenHelper private constructor(ctx: Context) :
    ManagedSQLiteOpenHelper(ctx, "MyDatabase", null, 1) {
    //初始化
    init {
        instance = this
    }

    //單例模式
    companion object {
        private var instance: MyDatabaseOpenHelper? = null

        @Synchronized
        fun getInstance(ctx: Context) = instance ?: MyDatabaseOpenHelper(ctx.applicationContext)
    }

    //創(chuàng)建數(shù)據(jù)庫時(shí) 做一些事情 比如創(chuàng)建一些默認(rèn)的表
    override fun onCreate(db: SQLiteDatabase) {


    }

    //數(shù)據(jù)庫版本更新 版本發(fā)生改變時(shí)做一些事情 比如刪除所有表
    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        // Here you can upgrade tables, as usual
        db.dropTable("User", true)
    }

    // Access property for Context
    val Context.database: MyDatabaseOpenHelper
        get() = MyDatabaseOpenHelper.getInstance(this)
}

代碼講解:

  1. MyDatabaseOpenHelper就是此項(xiàng)目的數(shù)據(jù)庫管理工具類,它有一個(gè)構(gòu)造參數(shù)Context,它繼承于框架提供的ManagedSQLiteOpenHelper。ManagedSQLiteOpenHelper有四個(gè)構(gòu)造參數(shù)分別是:context,數(shù)據(jù)庫名稱,數(shù)據(jù)庫工廠(默認(rèn)null就行),數(shù)據(jù)庫版本號(hào)

2.在 companion object中創(chuàng)建靜態(tài)方法,使用單例模式調(diào)用此類

3.在onCreate中,就是創(chuàng)建數(shù)據(jù)庫了,文檔中在這里創(chuàng)建了一個(gè)默認(rèn)表,但是我是為了每個(gè)表單獨(dú)創(chuàng)建了一個(gè)操作類,所以就沒有在這里建表。各人有不同的封裝思路,如果表很少的話,可以將數(shù)據(jù)庫相關(guān)代碼全部寫在MyDatabaseOpenHelper

4.其他代碼暫時(shí)不管

二 為你的每張表創(chuàng)建操作類

比如我這里有一個(gè)掃碼記錄表
包括三個(gè)字段:id | 掃描字符串 | 掃碼時(shí)間戳
我創(chuàng)建了一個(gè)類ScanRecordsDbProvider如下:

//主要負(fù)責(zé)掃描歷史記錄的增刪查
class ScanRecordsDbProvider {
    //數(shù)據(jù)庫操作
    private val database = MyDatabaseOpenHelper.getInstance(App.context)

    //初始化 調(diào)用createTable建表
    init {
        createTable()
    }

    //單例模式
    companion object {
        val instance: ScanRecordsDbProvider by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ScanRecordsDbProvider() }
        //表名
        private const val TABLE_NAME = "ScanRecords"
        //表字段名(id省略了)
        private const val COLUMN_CONTENT = "content"
        private const val COLUMN_TIMESTAMP = "timestamp"
    }


    //建表
    private fun createTable() {
        database.use {
            //檢查表是否存在 不存在則創(chuàng)建表
            createTable(
                TABLE_NAME, true,
                "id" to INTEGER + PRIMARY_KEY + UNIQUE,//主鍵 int型 唯一 遞增
                COLUMN_CONTENT to TEXT,
                COLUMN_TIMESTAMP to TEXT
            )
        }
    }


    //增加數(shù)據(jù)
    fun insertData(data: ScanRecordEntity) {
        database.use {
            insert(TABLE_NAME, COLUMN_CONTENT to data.content, COLUMN_TIMESTAMP to data.timestamp)
        }
    }


    //查詢所有數(shù)據(jù)
    fun queryAll(): ArrayList<ScanRecordEntity> {
        val list = ArrayList<ScanRecordEntity>()
        database.use {
            select(TABLE_NAME).exec {
                while (moveToNext()) {
                    val content = getString(getColumnIndex(COLUMN_CONTENT))
                    val timestamp = getString(getColumnIndex(COLUMN_TIMESTAMP))
                    list.add(ScanRecordEntity(content, timestamp))
                }

            }

        }
        //倒序
        list.reverse()
        return list
    }

    //清除所有數(shù)據(jù)
    fun clearAll() {
        database.use {
            delete(TABLE_NAME)
        }
    }

    //添加數(shù)據(jù)(多條)
    fun insertData(data: List<ScanRecordEntity>) {

    }


    //刪除表
    fun dropTable() {

    }


}

代碼解析:

  1. 成員變量database直接調(diào)用 MyDatabaseOpenHelper.getInstance(App.context)獲得,這里App.context也就是application的context

  2. 還是單例模式,在初始化init自動(dòng)建表。companion object 中完成單例模式并且給出表名和字段名(id省略了)

3.在createTable()函數(shù)中創(chuàng)建表,使用database.use{ }直接調(diào)用createTable方法,建表時(shí)確定每個(gè)字段的類型,比如id是INTEGER,并且是主鍵,不重復(fù)(自動(dòng)遞增),掃碼內(nèi)容字符串是TEXT也就是String。時(shí)間戳本來是long但是框架沒有提供,就使用TEXT 。其實(shí)在實(shí)際使用過程中前端的數(shù)據(jù)庫都是比較簡(jiǎn)單的,框架為我們提供了五個(gè)表字段基本類型:NULL, INTEGER, REAL, TEXT ,BLOB
但其實(shí)只用到INTEGER和TEXT就可以應(yīng)付99%的情況了。

4.insertData(data: ScanRecordEntity)添加單個(gè)數(shù)據(jù),代碼很簡(jiǎn)單

5.queryAll()查詢所有數(shù)據(jù),注意數(shù)據(jù)查詢出來后,要把每一行每一列的字段拿出來存到內(nèi)存。

三 調(diào)用表的操作類,進(jìn)行數(shù)據(jù)庫操作

例如我這里在activity中添加數(shù)據(jù)和查詢所有數(shù)據(jù):

    private val scanRecordsProvider = ScanRecordsDbProvider.instance
//添加數(shù)據(jù)
 scanRecordsProvider.insertData(ScanRecordEntity(result, timeUnit.getTimestampStr()))
//查詢數(shù)據(jù)
mData.addAll(scanRecordsProvider.queryAll())

不同的表根據(jù)不同的業(yè)務(wù),有不同的操作方法,所以具體需要表的哪些操作,自己在表操作類中自定義

到這里只是最簡(jiǎn)單的使用,比如更復(fù)雜的查詢,多表聯(lián)合查詢這些,看文檔慢慢擴(kuò)展吧。
最后還在再說一句,建議每張表對(duì)應(yīng)一個(gè)操作類,或者多張業(yè)務(wù)需求的表對(duì)應(yīng)一個(gè)操作類。這樣以后數(shù)據(jù)庫表比較多后,每個(gè)表的操作方法都封裝好了,代碼非常清楚。當(dāng)然,如果是非常簡(jiǎn)單的就一張表,就寫到數(shù)據(jù)庫helper類中都可以,這樣的封裝方式是有一些多余了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容