Android-11 Kotlin集成Realm

作者: 知小酌 | 来源:发表于2017-02-06 22:43 被阅读686次

    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

    相关文章

      网友评论

        本文标题:Android-11 Kotlin集成Realm

        本文链接:https://www.haomeiwen.com/subject/saouittx.html