Android十八章:Realm-in-android

Realm介绍

Realm是一个开源的ORM概念的(对象关系映射)移动数据库,可以在Android ,ios ,java各个平台上使用,性能秒杀sqlite等数据库比如(greendao)。

快速入门

只需两步

在整个项目的build.gradle中dependencies输入classpath “io.realm:realm-gradle-plugin:2.3.1”,这里要双引号。这里要双引号。这里要双引号。

buildscript {
    repositories {

        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
        classpath "io.realm:realm-gradle-plugin:2.3.1"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

在app的bulid.gradle输入apply plugin: 'realm-android'

apply plugin: 'com.android.application'
apply plugin: 'realm-android'

★以上操作完成了realm在as的配置了。

Realm的模型

自定义类要继承RealmObject,注意如果重载了带参数构造方法,这里必须要多写一个无参数的构造方法不然会抛出javac的异常。不要我问我为什么。

public class Dog extends RealmObject {
    private String name;
    private int age;

    public Dog() {

    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

如果类A中包含着其他类的集合这时候要用到ResultList<E>,比如

public class Person extends RealmObject {
    @PrimaryKey
    private long id;
    private String name;
    private RealmList<Dog> mDogRealmList;
    }

如果你的自定义类已经继承了其他父类,你也可以实现RealmModel来建造realm对象模型。

@RealmClass
public class User implements RealmModel {

    private String name;
    private int id;
    //...
}

Realm注解说明

@RealmClass 当实现RealmModel接口的类要加上这个注解。

@Required 修饰不能为空的成员变量

@Ignore 修饰不写入数据库的变量

@PrimaryKey 设置该成员变量为类的主键

@Index 加快查询速度,不过会让插入数据时变慢

Realm初始化

在自定义Applciation中Realm.init(this);

获取Realm实例

realm = Realm.getDefaultInstance();

这是获取默认配置的Realm,默认保存在data/data/packageName/files/default.realm 你也可以自定义RealmConfiguration,通常是自定义文件名,加密的key,数据库版本号和是否删除合并前的数据等。Realm实现了closeable接口,所以每次的getInstance,到最后关闭使用后都要调用close方法。比如在activity的ondestroy调用realm.close();

Realm写入

Realm是一个MVCC架构,同一线程的读写操作不影响获取数据,但是多线程读取写入操作就要用到事务来确保获取数据一致性和线程安全。的是放在事务transcation里面执行,确保整个事务的操作都被提交或者全部取消操作调用realm.cancelTranscation();,确保数据的一致性。

realm = Realm.getDefaultInstance();
realm.beginTransaction();
Dog d=new Dog("a",1);
Dog b=realm.copyToRealm(d);//这里的copyToRealm相当于深拷贝了一个d变量。对原来的d变量没任何影响。
b.setName("b");
realm.commitTransaction(); //最后往数据库写入一个dog变量b 

♥copyToRealm会深拷贝一个变量到数据库包括主键,如果主键重复就会抛出异常,拷贝之后主键不能修改。

当两个线程同时进行写入操作,另外一个会造成主线程阻塞,所以要调用异步事务避免主线程阻塞。

//同步新增数据
realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        Dog dog = realm.copyToRealm(new Dog(1, "2", 3));
        dog.setName("pp");
    }
});
//异步修改 查询
realm.executeTransactionAsync(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        Dog dog = realm.copyToRealm(dogOne);
        dog.setName("apple");

    }
}, new Realm.Transaction.OnSuccess() {
    @Override
    public void onSuccess() {
        RealmResults<Dog> list = realm.where(Dog.class).findAll();
        for (int i = 0; i < list.size(); i++) {
            Log.i(TAG, "onSuccess: " + list.toString());
        }
    }
});

realm的主键,在oncreate方法加入设置主键的RealmObject方法,下次调用oncreate没有判断主键是否exist就加入数据库就会报错。而在oncreate方法没加入没设置主键的realmobject类 ,下次调用oncreate方法就会在自启动数据库文件追加。

Realm 查询

查询都是返回一个RealmResults<E>对象支持以下查询条件。

  1. between(),greaterThan(), lessThan(), greaterThanOrEqualTo() 和lessThanOrEqualTo();
  2. equalTo()和notEqualTo()
  3. contains(),beginsWith()和endsWith()
  4. isNull()和isNotNull()
  5. isEmpty()和isNotEmpty()
RealmResults<Dog> list=realm.where(Dog.class).lessThan("age",1).findAll();
for (int i = 0; i < list.size(); i++) {
    Log.i(TAG, "execute: "+list.get(i).getName());
}

Realm修改

修改操作要在一个事务里面完成。

  dog = new Dog(1, "a", 1);
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                dog = realm.copyToRealm(dog);
                dog.setAge(2);
                dog.setName("kiki");


                RealmResults<Dog> list = realm.where(Dog.class).equalTo("id", 1).findAll();
                list.get(0).setName("ab");


               
            }
        });

RealmResult<E>的changeListener

监听RealmResult内容变化。

RealmResults<Dog> list = realm.where(Dog.class).lessThan("id", 3).findAll();


realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {

        Dog dog = realm.createObject(Dog.class);
        dog.setId(2);
        dog.setName("aaaa");
        dog.setAge(3);


    }
});
list.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {
    @Override
    public void onChange(RealmResults<Dog> element) {
        Log.i(TAG, "onChange: " + element.toString());
    }
});

//最后需要在activity或者fragment的生命周期比如ondestory调用
list.removeChangeListeners();//删除全部的listener
list。removeChangeListener(callback);//删除一个callback

Realm的删除

继续上面的例子查询id小于3的realmresult集合

list.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {
    @Override
    public void onChange(RealmResults<Dog> element) {
        element.deleteFirstFromRealm();//删除第一条数据
        element.deleteAllFromRealm();//删除全部数据
        element.deleteFromRealm(0);//删除指定数据
        element.deleteLastFromRealm();//删除最后一条数据
        element.get(1).deleteFromRealm();//删除指定obejct
    }
});

Realm添加一个json字符串

realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        realm.createObjectFromJson(Dog.class,"{\n" +
                "    \"id\": 1,\n" +
                "    \"name\": \"bili\",\n" +
                "    \"age\": 12\n" +
                "}");
    }
});

copyFromRealm,copyToRealm和createObject区别

  • copyFromRealm传入一个RealmObject 拷贝realm数据库中的一个变量并拷贝他的所有属性。
  • copyToRealm 传入一个Obeject 拷贝这个Object的所有属性到realm数据库中
  • createObject 传入一个class 并且赋值他的成员变量为默认值null 或者需要后期赋值使用

RealmResult<E> 使用

RealmResults<Dog> list = realm.where(Dog.class).findAll();
  list.sum("age");
  list.max("age");
  list.min("age");
  list.average("age");

比如获取dog类的所有对象,求age的总和,最大值,最小值,平均值

DynamicRealm

DynamicRealm是Realm的变种类,可以操作没继承RealmObject的类,操作类,当然是以字符串的形式操作,而不是RealmObject,他的默认配置少了schema版本号,migration合并信息的检查。

     DynamicRealm dynamicRealm = DynamicRealm.getInstance(new RealmConfiguration.Builder().build());
      dynamicRealm.executeTransaction(new DynamicRealm.Transaction() {
          @Override
          public void execute(DynamicRealm realm) {
              DynamicRealmObject person = realm.createObject("Person",1);
              person.setString("name", "kik");
              
          }
      });

Realm的close

Realm实现了closeable接口,所以每次的getInstance,到最后关闭使用后都要调用close方法。比如在activity的ondestroy调用realm.close();

比如在子线程getIntstance一次,需要在子线程结束前调用一次close();

class MyRunnable implements Runnable{

    @Override
    public void run() {
        try {
            Realm realm=Realm.getDefaultInstance();
        
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            realm.close();

        }
    }
}

Realm 版本迁移

如果realm版本是1,现在要升级realm版本是2并且数据解构改变了比如新增了一个RealmObejct的成员变量,如果default.realm存在旧数据,会升级失败。需要要设置migration合并规则。

要自定义一个RealmConfiguration变量 ,重写migrate方法判断oldVersion是上一个版本号,要做什么需求。

//你还可以做以下操作
addField("key",long.class);//加一个成员变量key
removeField("key");//去掉一个成员变量key
addRealmListField("dogs",schema.get("Dog"));//加上Realmlist变量dogs
addRealmObjectField("dog",schema.get("Dog"));//加上realmobject变量dog
transform(new RealmObjectSchema.Function(){
  public void apply(DynamicRealmObject obj){
    obj.set("fullname",obj.getString("firstName")+" "+obj.getString("lastName"))
  }
});//把firstname lastname赋值给fullname

比如版本升级加上key


    RealmMigration mRealmMigration=new RealmMigration() {
        @Override
        public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
            RealmSchema schema=realm.getSchema();
 /*
           //version 0
           class Dog

            private long id;
            private String name;
            private int age;

              //version 1
           class Dog
            private long key;
            private long id;
            private String name;
            private int age;

            */



            //version 0 to version 1
            if(oldVersion==1){
                schema.get("Dog")
                        .addField("key",long.class);
                       /* .addRealmObjectField("dogs",schema.get("Dog"))
                        .addRealmObjectField("dog",schema.get("Dog"));*/
                oldVersion++;
            }
        }
    };


  //最后
  realm = Realm.getInstance(PPApplicaion.mMigrationConfiguration);

总结

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

推荐阅读更多精彩内容