Anko-SQLite的使用

Anko是Kotlin库,可以使Android应用程序的开发变得更快,更轻松。它使您的代码干净且易于阅读,并且使您无需理会Android SDK for Java的粗糙之处。

Anko提供了许多扩展功能
github地址:https://github.com/Kotlin/anko
根据github上的内容引入到项目,这里贴出来的话以后肯定不是Anko最新版本了。

Anko的功能非常丰富,本文主要使用其为了简化SQLite的使用提供的数据库管理的功能Anko-SQLite
以下为使用方法,主要参考:https://github.com/Kotlin/anko/wiki/Anko-SQLite

一 为你的项目创建数据库管理工具类

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)
    }

    //创建数据库时 做一些事情 比如创建一些默认的表
    override fun onCreate(db: SQLiteDatabase) {


    }

    //数据库版本更新 版本发生改变时做一些事情 比如删除所有表
    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就是此项目的数据库管理工具类,它有一个构造参数Context,它继承于框架提供的ManagedSQLiteOpenHelperManagedSQLiteOpenHelper有四个构造参数分别是:context,数据库名称,数据库工厂(默认null就行),数据库版本号

2.在 companion object中创建静态方法,使用单例模式调用此类

3.在onCreate中,就是创建数据库了,文档中在这里创建了一个默认表,但是我是为了每个表单独创建了一个操作类,所以就没有在这里建表。各人有不同的封装思路,如果表很少的话,可以将数据库相关代码全部写在MyDatabaseOpenHelper

4.其他代码暂时不管

二 为你的每张表创建操作类

比如我这里有一个扫码记录表
包括三个字段:id | 扫描字符串 | 扫码时间戳
我创建了一个类ScanRecordsDbProvider如下:

//主要负责扫描历史记录的增删查
class ScanRecordsDbProvider {
    //数据库操作
    private val database = MyDatabaseOpenHelper.getInstance(App.context)

    //初始化 调用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 {
            //检查表是否存在 不存在则创建表
            createTable(
                TABLE_NAME, true,
                "id" to INTEGER + PRIMARY_KEY + UNIQUE,//主键 int型 唯一 递增
                COLUMN_CONTENT to TEXT,
                COLUMN_TIMESTAMP to TEXT
            )
        }
    }


    //增加数据
    fun insertData(data: ScanRecordEntity) {
        database.use {
            insert(TABLE_NAME, COLUMN_CONTENT to data.content, COLUMN_TIMESTAMP to data.timestamp)
        }
    }


    //查询所有数据
    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
    }

    //清除所有数据
    fun clearAll() {
        database.use {
            delete(TABLE_NAME)
        }
    }

    //添加数据(多条)
    fun insertData(data: List<ScanRecordEntity>) {

    }


    //删除表
    fun dropTable() {

    }


}

代码解析:

  1. 成员变量database直接调用 MyDatabaseOpenHelper.getInstance(App.context)获得,这里App.context也就是application的context

  2. 还是单例模式,在初始化init自动建表。companion object 中完成单例模式并且给出表名和字段名(id省略了)

3.在createTable()函数中创建表,使用database.use{ }直接调用createTable方法,建表时确定每个字段的类型,比如id是INTEGER,并且是主键,不重复(自动递增),扫码内容字符串是TEXT也就是String。时间戳本来是long但是框架没有提供,就使用TEXT 。其实在实际使用过程中前端的数据库都是比较简单的,框架为我们提供了五个表字段基本类型:NULL, INTEGER, REAL, TEXT ,BLOB
但其实只用到INTEGER和TEXT就可以应付99%的情况了。

4.insertData(data: ScanRecordEntity)添加单个数据,代码很简单

5.queryAll()查询所有数据,注意数据查询出来后,要把每一行每一列的字段拿出来存到内存。

三 调用表的操作类,进行数据库操作

例如我这里在activity中添加数据和查询所有数据:

    private val scanRecordsProvider = ScanRecordsDbProvider.instance
//添加数据
 scanRecordsProvider.insertData(ScanRecordEntity(result, timeUnit.getTimestampStr()))
//查询数据
mData.addAll(scanRecordsProvider.queryAll())

不同的表根据不同的业务,有不同的操作方法,所以具体需要表的哪些操作,自己在表操作类中自定义

到这里只是最简单的使用,比如更复杂的查询,多表联合查询这些,看文档慢慢扩展吧。
最后还在再说一句,建议每张表对应一个操作类,或者多张业务需求的表对应一个操作类。这样以后数据库表比较多后,每个表的操作方法都封装好了,代码非常清楚。当然,如果是非常简单的就一张表,就写到数据库helper类中都可以,这样的封装方式是有一些多余了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350