Android-11 Kotlin集成Realm

realm是一个跨平台移动数据库引擎,支持iOS、OS X(Objective-C和Swift)以及Android。相比SQLite,Realm更快并且具有很多现代数据库的特性,比如支持JSON,流式api,数据变更通知,以及加密支持,这些都为安卓开发者带来了方便;

下面我们来看看如何在Kotlin的项目中集成Realm

安装:

Realm 作为一个 Gradle 插件来安装需要如下两个步骤:

  1. 在项目的 build.gradle 文件中添加如下 class path 依赖
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "io.realm:realm-gradle-plugin:2.1.1"
    }
}

  1. 在 app 的 build.gradle 文件中应用 realm-android 插件
apply plugin: 'realm-android'

Realm数据模型定义需要继承RealmObject类:

package com.vslimit.kotlindemo.realmobj

import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import io.realm.annotations.RealmClass

/**
 * Created by vslimit on 17/2/4.
 */
@RealmClass
open class Book : RealmObject(){
    @PrimaryKey
    open var id:String? = ""
    open var name:String? = ""
    open var author:String? = ""
}

配置 Realm

首先要在App中添加:

Realm.init(this)

RealmConfiguration 用来配置要被创建的 Realm 的各种特性。最简配置如下所示:

RealmConfiguration config = new RealmConfiguration.Builder().build();

如上配置的 Realm 会被存储在 Context.getFilesDir() 并且命名为 default.realm。

我在项目中定义了一个RealmUtil

package com.vslimit.kotlindemo.util.realm

import io.realm.Realm
import io.realm.RealmConfiguration

/**
 * Created by vslimit on 16/11/8.
 */
class RealmUtil() {
    companion object {
        fun instant(): Realm {
            val config = RealmConfiguration.Builder().name("myrealm.realm").schemaVersion(1).migration(Migration.getInstance()).build()
            return Realm.getInstance(config)
        }
    }
}

数据库名字为myrealm

请务必注意到Realm的实例是线程单例化的,也就是说,在同一个线程内多次调用静态方法获得针对同路径的Realm,会返回同一个Realm实例。

如果在项目初始化的时候,需要初始化部分数据,则可以将先将数据插入到myrealm中,然后用将myrealm.realm放到assets文件夹下,配置realm时加上assetFile("myrealm.realm"),具体代码如下:

val config = RealmConfiguration.Builder().name("myrealm.realm").schemaVersion(2).migration(Migration.getInstance()).assetFile("myrealm.realm").build()

迁移

所有数据库都要处理模型改变的情况。Realm 的数据模型用标准 Java 对象来定义,改变数据模型只需要改变数据对象定义即可。

如果没有旧 Realm 数据文件存在,那么代码的改变即会反应到相应的 Realm 数据文件改变。但如果已经有旧版本的 Realm 数据文件存在,Realm 会抛出异常提示数据库文件需要迁移。请在相应的 RealmConfiguration 设置 schema 版本和 migration 代码来正确处理并避免该异常抛出;

这里定义了一个Migrate,不过目前是空的:

package com.vslimit.kotlindemo.util.realm;

import io.realm.DynamicRealm;
import io.realm.RealmMigration;
import io.realm.RealmSchema;

/**
 * Created by vslimit on 17/1/23.
 */
public class Migration implements RealmMigration {

    private static Migration instance = null;

    static {
        instance = new Migration();
    }

    private Migration() {
    }

    public static Migration getInstance() {
        return instance;
    }

    @Override
    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
        RealmSchema schema = realm.getSchema();
        if (oldVersion == 0) {
            oldVersion++;
        }
//        if (oldVersion == 1) {
//            oldVersion++;
//        }
    }
}

Realm扩展类RealmExtensions.kt

package com.vslimit.kotlindemo.extensions

import io.realm.Realm
import io.realm.RealmObject
import io.realm.RealmQuery
import io.realm.RealmResults

/**
 * Created by Kittinun Vantasin on 10/20/14.
 */

fun <T : RealmObject> Realm.create(clazz: Class<T>, f: (it: T) -> Unit): T {
    beginTransaction()
    val realmObject = createObject(clazz)
    f(realmObject)
    commitTransaction()
    return realmObject
}

fun <T : RealmObject> Realm.create(it: T): T {
    beginTransaction()
    val realmObject = copyToRealm(it)
    commitTransaction()
    return realmObject
}

fun <T : RealmObject> Realm.createOrUpdate(it: T): T {
    beginTransaction()
    val realmObject = copyToRealmOrUpdate(it)
    commitTransaction()
    return realmObject
}

fun <T : RealmObject> Realm.deleteAll(clazz: Class<T>) {
    beginTransaction()
    val results = where(clazz).findAll()
    results.deleteAllFromRealm()
    commitTransaction()
}

fun <T : RealmObject> Realm.delete(clazz: Class<T>, key: String, value: String) {
    beginTransaction()
    val results = where(clazz).equalTo(key, value).findAll()
    results.deleteAllFromRealm()
    commitTransaction()
}

fun <T : RealmObject> Realm.query(clazz: Class<T>, conditionMap: Map<String, String>?): RealmResults<T> {
    val query: RealmQuery<T> = where(clazz)
    if (conditionMap != null) {
        for ((key, value) in conditionMap) {
            query.equalTo(key, value)
        }
    }
    return query.findAll()
}

fun <T : RealmObject> Realm.show(clazz: Class<T>,conditionMap: Map<String, String>?): T {
    val query: RealmQuery<T> = where(clazz)
    if (conditionMap != null) {
        for ((key, value) in conditionMap) {
            query.equalTo(key, value)
        }
    }
    return query.findFirst()
}

fun <T : RealmObject> Realm.findAll(clazz: Class<T>): RealmResults<T> {
    return query(clazz, null)
}

下面我们来看看实际demo,布局代码还是之前的一个Textview和三个Button

package com.vslimit.kotlindemo.fragment

import android.os.Bundle
import android.util.Log
import android.view.View
import com.vslimit.kotlindemo.R
import com.vslimit.kotlindemo.extensions.*
import com.vslimit.kotlindemo.realmobj.Book
import com.vslimit.kotlindemo.util.realm.RealmUtil
import io.realm.Realm
import kotlinx.android.synthetic.main.fragment_companys.*
import org.jetbrains.anko.async
import org.jetbrains.anko.onClick
import java.util.*
import kotlin.properties.Delegates


/**
 * Created by vslimit on 16/12/31.
 */
class BookListFragment : BaseFragment() {
    override val layoutResourceId: Int = R.layout.fragment_companys

    var realm: Realm by Delegates.notNull()

    companion object {
        fun getInstance(): BookListFragment {
            return BookListFragment()
        }
    }

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        init()
        showBtn.onClick {
            val book = realm.show(Book::class.java, mapOf("author" to "vslimit"))
            Log.d("BOOK:::", book.name)
            val name = book.name
            async() { nameTv.text = name }
        }

        updateBtn.onClick {
            val book = realm.show(Book::class.java, mapOf("author" to "vslimit"))
            book.name = "update name"
            realm.createOrUpdate(book)
        }

        insertBtn.onClick {
            val book = Book()
            book.id = UUID.randomUUID().toString()
            book.name = "Kotlin Realm Android"
            book.author = "vslimit"
            realm.create(book)
        }
    }

    override fun onResume() {
        super.onResume()
        realm.close()
    }

    fun init() {
        realm = RealmUtil.instant()
        val results = realm.findAll(Book::class.java)
        val sizeTxt = "BOOK SIZE:${results.size}"
        async() {
            nameTv.text = sizeTxt
        }
    }

    override fun onDestroy() {
        super.onDestroy()
    }
}

这里需要注意的
请谨记:Realm、RealmObject 和RealmResults 实例都不可以跨线程使用。

本文只是对Kotlin集成Realm做了简单的介绍,更多的内容,请查看官方文档:传送门

最后引用官方的一句话:
Realm 完全兼容 Kotlin 语言,但有些地方需要注意:

  • 你的模型类需要是开放的(open)。
  • 你可能需要在某些情况下添加注解 @RealmCLass 以保证编译通过。这是由于当前 Kotlin 注解处理器的一个限制。
  • 很多 Realm API 引用了 Java 类。你必须在编译依赖中添加 org.jetbrains.kotlin:kotlin-reflect:${kotlin_version}。

本文中的所有代码已经提交到git上了,大家如果喜欢就去git下star下吧。

Realm的代码详见:https://github.com/vslimit/kotlindemo

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

推荐阅读更多精彩内容