前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android十八章:Realm-in-android

Android十八章:Realm-in-android

作者头像
ppjun
发布2018-09-05 11:51:57
9920
发布2018-09-05 11:51:57
举报
文章被收录于专栏:ppjun专栏ppjun专栏

Realm介绍

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

快速入门

只需两步

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

代码语言:javascript
复制
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'

代码语言:javascript
复制
apply plugin: 'com.android.application'
apply plugin: 'realm-android'

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

Realm的模型

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

代码语言:javascript
复制
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>,比如

代码语言:javascript
复制
public class Person extends RealmObject {
    @PrimaryKey
    private long id;
    private String name;
    private RealmList<Dog> mDogRealmList;
    }

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

代码语言:javascript
复制
@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实例

代码语言:javascript
复制
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();,确保数据的一致性。

代码语言:javascript
复制
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会深拷贝一个变量到数据库包括主键,如果主键重复就会抛出异常,拷贝之后主键不能修改。

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

代码语言:javascript
复制
//同步新增数据
realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        Dog dog = realm.copyToRealm(new Dog(1, "2", 3));
        dog.setName("pp");
    }
});
代码语言:javascript
复制
//异步修改 查询
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()
代码语言:javascript
复制
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修改

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

代码语言:javascript
复制
  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内容变化。

代码语言:javascript
复制
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集合

代码语言:javascript
复制
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字符串

代码语言:javascript
复制
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> 使用

代码语言:javascript
复制
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合并信息的检查。

代码语言:javascript
复制
     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();

代码语言:javascript
复制
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是上一个版本号,要做什么需求。

代码语言:javascript
复制
//你还可以做以下操作
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

代码语言:javascript
复制
    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
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.02.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Realm介绍
  • 快速入门
  • Realm的模型
  • Realm注解说明
  • Realm初始化
  • Realm写入
  • Realm 查询
  • Realm修改
  • RealmResult<E>的changeListener
  • Realm的删除
  • Realm添加一个json字符串
  • copyFromRealm,copyToRealm和createObject区别
  • RealmResult<E> 使用
  • DynamicRealm
  • Realm的close
  • Realm 版本迁移
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档