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  Realm.create(clazz: Class, f: (it: T) -> Unit): T {
    beginTransaction()
    val realmObject = createObject(clazz)
    f(realmObject)
    commitTransaction()
    return realmObject
}

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

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

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

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

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

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

fun  Realm.findAll(clazz: Class): RealmResults {
    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)