目录

1、Realm简介

2、环境配置

3、初始化Realm

4、创建实体

5、增

6、删

7、改

8、查

9、异步操作

10、数据库数据更新监听

11、json转对象,插入数据库

12、Demo地址 https://github.com/baitutang1221/DemoRealm-master

==========================================

一、Realm简介

数据库Realm,是用来替代sqlite的一种解决方案,它有一套自己的数据库存储引擎,比sqlite更轻量级,拥有更快的速度,并且具有很多现代数据库的特性,比如支持JSON,流式api,数据变更通知,自动数据同步,简单身份验证,访问控制,事件处理,最重要的是跨平台,目前已有Java,Objective C,Swift,React-Native,Xamarin这五种实现。

二、环境配置

(1). 在项目的build文件加上 classpath "io.realm:realm-gradle-plugin:2.0.2"

buildscript {
repositories {
jcenter()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:2.0.2"
}
}

(2) 在app的build文件加上

apply plugin: 'realm-android'

三、初始化Realm

(1) 在Application的oncreate()方法中Realm.init()

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Realm.init(this);
}
}

(2)在Application的oncreate()方法中对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);
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)在AndroidManifest.xml配置自定义的Application

<application
android:name=".MyApplication"
...
/>

四、创建实体

(1)新建一个类继承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;
}
}

多对多的关系:

public class Contact extends RealmObject {
public String name;
public RealmList<Email> emails;
} public class Email extends RealmObject {
public String address;
public boolean active;
}

(2)其他相关说明

1、支持的数据类型:

boolean, byte, short, int, long, float, double, String, Date and byte[]

在Realm中byte, short, int, long最终都被映射成long类型

2、注解说明

@PrimaryKey

①字段必须是String、 integer、byte、short、 int、long 以及它们的封装类Byte, Short, Integer, and Long

②使用了该注解之后可以使用copyToRealmOrUpdate()方法,通过主键查询它的对象,如果查询到了,则更新它,否则新建一个对象来代替。

③使用了该注解将默认设置(@index)注解

④使用了该注解之后,创建和更新数据将会慢一点,查询数据会快一点。

@Required

数据不能为null

@Ignore

忽略,即该字段不被存储到本地

@Index

为这个字段添加一个搜索引擎,这将使插入数据变慢、数据增大,但是查询会变快。建议在需要优化读取性能的情况下使用。

五、增

(1)实现方法一:事务操作

类型一 :新建一个对象,并进行存储

Realm realm=Realm.getDefaultInstance();

realm.beginTransaction();
User user = realm.createObject(User.class); // Create a new object
user.setName("John");
user.setEmail("john@corporation.com");
realm.commitTransaction();

类型二:复制一个对象到Realm数据库

Realm realm=Realm.getDefaultInstance();

User user = new User("John");
user.setEmail("john@corporation.com"); // Copy the object to Realm. Any further changes must happen on realmUser
realm.beginTransaction();
realm.copyToRealm(user);
realm.commitTransaction();

(2)实现方法二:使用事务块

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

切记,Realm数据库的主键字段不是自动增长的,如果有主键,需要自己设置,做添加的时候如果不给id字段值,默认会为0。

后面再添加会报错,说id为0的数据已经存在。

尤其是批量添加的时候要注意,当心出现只添加了一条记录的悲剧。

六、删

    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方法进行删除

七、改

Realm  mRealm=Realm.getDefaultInstance();

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

同样也可以用事物块来更新数据

八、查

(1)查询全部

查询结果为RealmResults

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

(2)条件查询

    public Dog queryDogById(String id) {
Realm mRealm=Realm.getDefaultInstance();
Dog dog = mRealm.where(Dog.class).equalTo("id", id).findFirst();
return dog;
}

常见的条件如下(详细资料请查官方文档):

可拼接查询条件如下

//.or() 或者

//.beginsWith() 以xxx开头

//.endsWith() 以xxx结尾

//.greaterThan() 大于

//.greaterThanOrEqualTo() 大于或等于

//.lessThan() 小于

//.lessThanOrEqualTo() 小于或等于

//.equalTo() 等于

//.notEqualTo() 不等于

//.findAll() 查询所有

//.average() 平均值

//.beginGroup() 开始分组

//.endGroup() 结束分组

//.between() 在a和b之间

//.contains() 包含xxx

//.count() 统计数量

//.distinct() 去除重复

//.findFirst() 返回结果集的第一行记录

//.isNotEmpty() 非空串

//.isEmpty() 为空串

//.isNotNull() 非空对象

//.isNull() 为空对象

//.max() 最大值

//.maximumDate() 最大日期

//.min() 最小值

//.minimumDate() 最小日期

//.sum() 求和

(3)对查询结果进行排序

    /**
* query (查询所有)
*/
public List<Dog> queryAllDog() {
RealmResults<Dog> dogs = mRealm.where(Dog.class).findAll();
/**
* 对查询结果,按Id进行排序,只能对查询结果进行排序
*/
//增序排列
dogs=dogs.sort("id");
//降序排列
dogs=dogs.sort("id", Sort.DESCENDING);
return mRealm.copyFromRealm(dogs);
}

(4)其他查询

sum,min,max,average只支持整型数据字段

   /**
* 查询平均年龄
*/
private void getAverageAge() {
double avgAge= mRealm.where(Dog.class).findAll().average("age");
} /**
* 查询总年龄
*/
private void getSumAge() {
Number sum= mRealm.where(Dog.class).findAll().sum("age");
int sumAge=sum.intValue();
} /**
* 查询最大年龄
*/
private void getMaxId(){
Number max= mRealm.where(Dog.class).findAll().max("age");
int maxAge=max.intValue();
}

九、异步操作

大多数情况下,Realm的增删改查操作足够快,可以在UI线程中执行操作。但是如果遇到较复杂的增删改查,或增删改查操作的数据较多时,就可以子线程进行操作。

(1)异步增:

    private void addCat(final Cat cat) {
RealmAsyncTask addTask= mRealm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealm(cat);
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
ToastUtil.showShortToast(mContext,"收藏成功");
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
ToastUtil.showShortToast(mContext,"收藏失败");
}
});
}

最后在销毁Activity或Fragment时,要取消掉异步任务

@Override
protected void onDestroy() {
super.onDestroy();
if (addTask!=null&&!addTask.isCancelled()){
addTask.cancel();
}
}

注意:如果当Acitivity或Fragment被销毁时,在OnSuccess或OnError中执行UI操作,将导致程序奔溃 。

用RealmAsyncTask .cancel();可以取消事务在onStop中调用,避免crash。

public void onStop () {
if (transaction != null && !transaction.isCancelled()) {
transaction.cancel();
}
}

(2)异步删

    private void deleteCat(final String id, final ImageView imageView){
RealmAsyncTask deleteTask= mRealm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Cat cat=realm.where(Cat.class).equalTo("id",id).findFirst();
cat.deleteFromRealm(); }
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
ToastUtil.showShortToast(mContext,"取消收藏成功");
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
ToastUtil.showShortToast(mContext,"取消收藏失败");
}
});
}

最后在销毁Activity或Fragment时,要取消掉异步任务

@Override
protected void onDestroy() {
super.onDestroy();
if (deleteTask!=null&&!addTask.isCancelled()){
deleteTask.cancel();
}
}

(3)异步改

RealmAsyncTask  updateTask=   mRealm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Cat cat=realm.where(Cat.class).equalTo("id",mId).findFirst();
cat.setName(name);
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
ToastUtil.showShortToast(UpdateCatActivity.this,"更新成功"); }
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
ToastUtil.showShortToast(UpdateCatActivity.this,"失败成功");
}
});

最后在销毁Activity或Fragment时,要取消掉异步任务

@Override
protected void onDestroy() {
super.onDestroy();
if (updateTask!=null&&!addTask.isCancelled()){
updateTask.cancel();
}
}

(4)异步查

     RealmResults<Cat>   cats=mRealm.where(Cat.class).findAllAsync();
cats.addChangeListener(new RealmChangeListener<RealmResults<Cat>>() {
@Override
public void onChange(RealmResults<Cat> element) {
element= element.sort("id");
List<Cat> datas=mRealm.copyFromRealm(element);
}
});

最后在销毁Activity或Fragment时,要取消掉异步任务

 @Override
protected void onDestroy() {
super.onDestroy();
cats.removeChangeListeners();
}

十, 数据库数据更新监听

MainActivity代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mRealm = Realm.getDefaultInstance();
userDao = new UserDao(mRealm); //... /**
* 数据库数据更新监听
*/
mRealm.addChangeListener(this);
} //... @Override
public void onChange(Realm element) {
findAll();
} @Override
protected void onDestroy() {
userDao = null;
mRealm.close();
super.onDestroy();
}

十一, json转对象,插入数据库

Realm还是个很nice的功能就是将Json字符串转化为对象,厉害了我的Realm

(直接借用官方的例子)

// 一个city model
public class City extends RealmObject {
private String city;
private int id;
// getters and setters left out ...
}
// 使用Json字符串插入数据
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.createObjectFromJson(City.class, "{ city: \"Copenhagen\", id: 1 }");
}
});
// 使用InputStream插入数据
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
try {
InputStream is = new FileInputStream(new File("path_to_file"));
realm.createAllFromJson(City.class, is);
} catch (IOException e) {
throw new RuntimeException();
}
}
});

Realm 解析 JSON 时遵循如下规则:

使用包含空值(null)的 JSON 创建对象:

对于非必须(可为空值的属性),设置其值为 null;

对于必须(不可为空值的属性),抛出异常;

使用包含空值(null)的 JSON 更新对象:

对于非必须(可为空值的属性),设置其值为 null;

对于必须(不可为空值的属性),抛出异常;

使用不包含对应属性的 JSON: * 该属性保持不变

版本升级的问题,参考:http://www.jianshu.com/p/37af717761cc

参照资料:

http://www.jianshu.com/p/37af717761cc

https://www.2cto.com/kf/201607/526365.html

【Android开发】【数据库】Realm For Android的更多相关文章

  1. Android开发数据库三层应用-DataSnap

    Android开发数据库三层应用-DataSnap http://www.2ccc.com/news/Html/?1517.html 核心提示:我觉得Delphi最强大的的功能之一就是开发数据库三层应 ...

  2. Android开发数据库之第三方ORM框架(GreenDao)

    移动APP追求追求功能实现的同一时候,用户体验很重要.開始APP的同一时候.要时刻的切换开发人员的角色,如你开发的时候.是 站在APP的开发角色,处于生产者的位置:当你測试的时候.你应该把自己放在用户 ...

  3. Android开发工具全面转向Android Studio(3)——AS project/module的目录结构(与Eclipse对比)

    如果AS完全还没摸懂的,建议先看下Android开发工具全面转向Android Studio(2)——AS project/module的CRUD. 注:以下以Windows平台为标准,AS以目前最新 ...

  4. Android开发工具全面转向Android Studio(2)——AS project/module的CRUD

    本文有些地方可能需要衔接Android开发工具全面转向Android Studio(1)——准备开发环境,读起来效果会更好. 这个世界很奇妙,所有的东西离不开CRUD,即增删改查.即使人本身也遵循这个 ...

  5. 收集整理Android开发所需的Android SDK、开发中用到的工具、Android开发教程、Android设计规范,免费的设计素材等。

    AndroidDevTools Android Dev Tools官网地址:www.androiddevtools.cn 收集整理Android开发所需的Android SDK.开发中用到的工具.An ...

  6. 配置cordova的android开发环境(无android studio)

    原文:配置cordova的android开发环境(无android studio) 趁元旦放假想试一下cordova,不想安装庞大的android studio,所以想最小化安装,居然花了一整天的时间 ...

  7. Eclipse搭建Android开发环境并运行Android项目

    Eclipse搭建Android开发环境并运行Android项目 (详细) 安装环境: window 10 64位 安装工具: JDK.Eclipse.SDK.ADT 安装步骤: 1.JAVA JDK ...

  8. android开发--数据库(更新或者降低版本)

    Andoird的SQLiteOpenHelper类中有一个onUpgrade方法. 1. 帮助文档里说的"数据库升级"是指什么? 你开发了一个应用,当前是1.0版本.该程序用到了数 ...

  9. Android开发学习之路--Android系统架构初探

    环境搭建好了,最简单的app也运行过了,那么app到底是怎么运行在手机上的,手机又到底怎么能运行这些应用,一堆的电子元器件最后可以运行这么美妙的界面,在此还是需要好好研究研究.这里从芯片及硬件模块-& ...

  10. Android开发学习之路-Android中使用RxJava

    RxJava的核心内容很简单,就是进行异步操作.类似于Handler和AsyncTask的功能,但是在代码结构上不同. RxJava使用了观察者模式和建造者模式中的链式调用(类似于C#的LINQ). ...

随机推荐

  1. Chapter08 面向对象(中级)

    Chapter08 面向对象(中级) 8.1 IDEA的使用 1. 快捷键 删除当前行, 默认是 ctrl + Y 自己配置 ctrl + d 复制当前行, 自己配置 ctrl + alt + 向下光 ...

  2. 使用Three.js实现神奇的3D文字悬浮效果

    声明:本文涉及图文和模型素材仅用于个人学习.研究和欣赏,请勿二次修改.非法传播.转载.出版.商用.及进行其他获利行为. 背景 在 Three.js Journey 课程示例中,提供了一个使用 Thre ...

  3. zookeeper的JAVA API使用

    1.创建连接 2.创建节点 3.监听信息 Watcher.class 4.获取节点 Stat stat = new Stat(); zk.getData(Path,true,stat); 5.修改节点 ...

  4. Wordpress Calendar Event Multi View < 1.4.01 反射型xss漏洞(CVE-2021-24498)

    简介 WordPress是Wordpress基金会的一套使用PHP语言开发的博客平台.该平台支持在PHP和MySQL的服务器上架设个人博客网站.WordPress 插件是WordPress开源的一个应 ...

  5. Mysql 8.0 配置主从备份

    my.ini文件的位置 mysql 8.0安装完过后没有my.ini疑惑了我好久,最后发现,配置文件在,C盘的一个隐藏文件夹里面 具体路径如下图 主库配置 修改主库INI文件 在[mysqld]节点添 ...

  6. CF1386C口胡

    自己在物理课上编了一道题,大概就是这题把删除区间的边改为保留区间的边...都不觉得判断短路和判断二分图有点儿像吗 题意:给定一张无向图,每次暂时删除一个区间内的边,问删除后这个区间是否为二分图. 首先 ...

  7. matlab语法基础(处理一点数据)

    1.声明函数,返回参数data,函数名为simutrack function data=simutrack(x0,y0) 2.%用于标注,注释 3.平方 ^2 4.二维零矩阵 [0 0;0 0] 5. ...

  8. Redis 大 key 问题总结

    多大的 key 算大? 阿里云Redis 最佳实践中提到 合理的 Key 中 Value 的字节大小,推荐小于10 KB.过大的 Value 会引发数据倾斜.热点Key.实例流量或 CPU 性能被占满 ...

  9. 使用阿里云镜像站NTP服务搭建NTP服务器(基于CentOS 7系统)

    镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 一.NTP服务器介绍 网络时间协议(Network Time Protocol,NTP)服务器,也就是日常所说的NTP服务器,用来提供同步时间服务 ...

  10. redis的事件处理机制

    redis的事件处理机制 redis是单进程,单线程模型,与nginx的多进程不同,与golang的多协程也不同,"工作的工人"那么少,可那么为什么redis能这么快呢? epol ...