realm学习

为什么用realm

android开发不仅仅是从网上获取数据并且展示,有时候我们需要把数据保存到我们本地,一般我们会想到用file,sp或者数据库sqlite,file的方式主要是IO流操作,sp是其实是使用xml的方式以键值对形式存储基本数据类型的数据。但是对于app中有复杂筛选查询的操作,file和sp都不能满足了.虽然sqlite可以满足有大量复杂查询要求的缓存数据操作。但是sqlite的使用略复杂,代码量很大.这时候就需要一种轻量级的数据库.Realm是一个可以替代SQLite以及ORM Libraries的轻量级数据库。

realm的优势
  • 相比SQLite,Realm更快并且具有很多现代数据库的特性,比如除了基本数据类型之外,还支持JSON.流式api,数据变更通知,以及加密支持
  • realm是一个跨平台移动数据库引擎,支持iOS、OS X(Objective-C和Swift)以及Android。这些都为移动端开发者带来了方便。
  • 性能比较高
  • 使用简单
使用方法

1.在项目的build.grade中配置

apply plugin: 'realm-android'
buildscript {
    repositories {
        jcenter()
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        classpath "io.realm:realm-gradle-plugin:1.0.0"
    }
}

2.初始化Realm,并进行相关配置.(Realm是框架的核心所在,是我们构建数据库的访问点,使用建造者模式构建对象。)

默认配置,

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    // The Realm file will be located in Context.getFilesDir() with name "default.realm"
    Realm.init(this);//初始化realm
    RealmConfiguration config = new RealmConfiguration.Builder().build();//默认配置
    Realm.setDefaultConfiguration(config);
  }
}

自定义配置

    public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    Realm.init(this);//初始化
    //自定义配置
    RealmConfiguration config = new  RealmConfiguration.Builder()
                                         .name("myRealm.realm")
                                         .deleteRealmIfMigrationNeeded()
                                         .build();
    Realm.setDefaultConfiguration(config);
  }
}

3.创建实体RealmObject(这是我们自定义的realm数据模型。创建数据模型的行为将会影响到数据库的结构。要创建一个数据模型,我们只需要继承RealmObject,然后设计我们想要存储的属性即可。)

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

@PrimaryKey
private String id;


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;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}
}

4.增

a.使用事务操作,新建一个对象,并且进行存储
Realm realm=Realm.getDefaultInstance();

realm.beginTransaction();//开启一个事务
User user = realm.createObject(User.class); //创建一个对象
user.setName("John");
user.setEmail("john@corporation.com");
realm.commitTransaction();//提交事务

b.使用事务块
Realm mRealm=Realm.getDefaultInstance();

final User user = new User("John");//创建对象
user.setEmail("john@corporation.com");

mRealm.executeTransaction(new Realm.Transaction() {//事务块
            @Override
            public void execute(Realm realm) {
            
            realm.copyToRealm(user);
               
            }
        });

5.删. (RealmResults:这个类是执行任何查询请求后所返回的类,其中包含了一系列的Object对象。和List类似,我们可以用下标语法来对其进行访问,并且还可以决定它们之间的关系。不仅如此,它还拥有许多更强大的功能,包括排序、查找等等操作。
)

Realm  mRealm=Realm.getDefaultInstance();

final RealmResults<Dog> dogs=  mRealm.where(Dog.class).findAll();

    mRealm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
        
            Dog dog=dogs.get(5);
            dog.deleteFromRealm();
            //删除第一个数据
            dogs.deleteFirstFromRealm();
            //删除最后一个数据
            dogs.deleteLastFromRealm();
            //删除位置为1的数据
            dogs.deleteFromRealm(1);
            //删除所有数据
            dogs.deleteAllFromRealm();
        }
    });

上面的代码是用事务块进行删除,跟增加操作一样,也可以用事务beginTransaction和commitTransaction方法进行删除

6.改

RealmObject是自动更新的,比如你将一个数据读取出来后,又做了修改,修改会马上在数据中生效,不需要你再
将数据保存到数据库

Realm  mRealm=Realm.getDefaultInstance();

Dog dog = mRealm.where(Dog.class).equalTo("id", id).findFirst();
mRealm.beginTransaction();
dog.setName(newName);
mRealm.commitTransaction();

也可以用事务块来进行修改

7.查

a.查询全部

 public List<Dog> queryAllDog() {
        Realm  mRealm=Realm.getDefaultInstance();
    
        RealmResults<Dog> dogs = mRealm.where(Dog.class).findAll();
        
        return mRealm.copyFromRealm(dogs);
    }

b.条件查询

  public Dog queryDogById(String id) {
    Realm  mRealm=Realm.getDefaultInstance();

    Dog dog = mRealm.where(Dog.class).equalTo("id", id).findFirst();
    return dog;
}

还有其他的条件:

  • between(), greaterThan(), lessThan(), greaterThanOrEqualTo() & lessThanOrEqualTo()

  • equalTo() & notEqualTo()

  • contains(), beginsWith() & endsWith()

  • isNull() & isNotNull()

  • isEmpty() & isNotEmpty()

8.使用realm来操作数据库,尽管这些操作很快,但是还是建议放在后台进行。可以在回调中更新ui

realm.executeTransactionAsync(new Realm.Transaction() {  
        @Override  
        public void execute(Realm bgRealm) {  
            User user = bgRealm.createObject(User.class);  
            user.setName("John");  
            user.setEmail("john@corporation.com");  
        }  
    }, new Realm.Transaction.OnSuccess() {  
        @Override  
        public void onSuccess() {  
            // Transaction was a success.  
        }  
    }, new Realm.Transaction.OnError() {  
        @Override  
        public void onError(Throwable error) {  
            // Transaction failed and was automatically canceled.  
        }  
    });

最后,我们要及时关闭realm任务,避免程序crash

public void onDestroy () {  
if (transaction != null && !transaction.isCancelled()) {  
    transaction.cancel();  
}  
}
Realm的一些坑

1.查询到的结果数据 不能跨线程使用.例如在主线程中查到的结果 在线程中想使用 需要在子线程中再查一次

2.realm对象不能跨线程使用.主线程中获取的realm对象, 不能在子线程中使用.需要重新调用getDefaultInstance()在子线程中获取另一个realm对象

3.当query到的数据要被使用时, realm数据库是要在开启的状态下的, 这样数据才能通过数据库链接访问到.在数据使用完毕后 需要把数据库关闭.一般选在在页面onDestory()的方法中 调用realm.close()方法关闭数据库链接.但如果网络请求数据的回调在页面关闭之后发生 也就是realm.close()调用了之后 又使用了同一个realm数据库链接查询数据
此时回报错误This Realm instance has already been closed, making it unusable.
解决办法是
如果还想使用同一个realm链接
先判断realm.isClosed()
数据库链接是否关闭了 如果关闭了重新打开一个新的数据库链接 使用完之后再将新的数据库链接关闭

4.如果想在Realm.close()之后继续操作查询得到的对象,只能复制一份数据传出来.

5.如果直接修改或删除query得到的数据,必须在transaction中完成.

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

推荐阅读更多精彩内容