0
点赞
收藏
分享

微信扫一扫

Realm试用


鉴于公司之前一直在使用SQLCipher+Afinal(数据库部分),然后有些根深蒂固的错误,十分期望能换种加密方式。可是,除了SQLCipher,百度了一下没找到什么新的。无意中发现了Realm,看起来还挺好用,决定拿来踩踩坑。

realm导入:
module的gradle:

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

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

官方地址:github:​​https://github.com/realm/realm-java​​​
1.初始化
初始化的部分,跟SQLite原生一样都要传个Context,想着要不用getApplicationContext()算了,无意中发现居然有个getDefaultInstance(),感觉非常满意,就它了,于是又了下面的初始化:
Application中:

private void initRealm() {
Realm.init(this);
RealmConfiguration config = new RealmConfiguration.Builder()
.name(Config.dbName)
.schemaVersion(Config.dbVersion)
.encryptionKey(Config.dbKey.getBytes())
.migration(DBUtil.getIntance())//升级数据库处理类(实现RealmMigration接口)
.build();
Realm.setDefaultConfiguration(config);

这里讲几个点:

  1. 建议做个配置文件,方便查询和修改
  2. 方法解释
    (1)Realm.init(this);//这句是初始化一定要加
    (2)RealmConfiguration这个类用于配置realm的一些属性
    name - 数据库名
    schemaVersion - 数据库版本号,用于识别是否升级
    encryptionKey - 密钥,用于加密数据库,只能定64个字母长的String再getBytes(),否则会提示位数不符合的异常,或者按照官方的:

byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
RealmConfiguration config = new RealmConfiguration.Builder()
.encryptionKey(key)
.build();

如果用官方的注意调试,再查看key值,因为random会导致每次生成的字串都不一样,官方声称这是一种很傻的做法,不过官方两个链接进不去了,所以暂时自己定个密钥算了。

    migration - 定义升级的类 当新版和旧版realm版本不同时,会对实现RealmMigration接口的类调用相应的方法

2.model - 数据库表行
可以定义注解:
@PrimaryKey(主键,没有自增长)
@Index(加快该字段查询速度,减慢该字段插入速度)
@Ignore(忽略该字段,不放入数据库中)
@Requied(非空字段)

注意该类一定要继承RealmObject,据说可以只实现RealmModel,但貌似会报错。
该model还有一个奇葩属性,这里一定要提一下:
除了第一次set,其他时候不能随意set!
否则会报错:只能在update的事务中更新,各种copy都不行
感觉这个特性很坑啊,有的时候编辑,如果没有保存是要恢复原状的,你这让我咋弄咧?

关于model,还有一点要注意:
一定不能重写toString()方法,会报错,这个坑我找了好久才发现= =

为此,将数据库model和普通model添加了转换,事例如下:
数据库User:

public class User extends RealmObject
private String id;
private String name;

public String getId() {
return id;
}

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

public String getName() {
return name;
}

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

public NormalUser toNormalUser(){
NormalUser user = new NormalUser();
user.setId(id);
user.setName(name);
return

普通User:

public class NormalUser {
private String id;
private String name;

public String getId() {
return id;
}

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

public String getName() {
return name;
}

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

public User toDBUser(){
User user = new User();
user.setId(id);
user.setName(name);
return

接下来写版本更新和获取数据库:

public class DBUtil implements RealmMigration
private static DBUtil sIntance;
public DBUtil() {
}

/**
* 双检索单例
* @return
public static DBUtil getIntance(){
if (sIntance == null) {
synchronized (DBUtil.class) {
if (sIntance == null) {
sIntance = new DBUtil();
}
}
}



return sIntance;
}

/**
* 获取realm对象
* @return
public Realm getRealm(){
Realm realm =getDefaultInstance();
return realm;
}

/**
* 版本升级处理
* @param realm
* @param oldVersion
* @param
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
RealmSchema schema = realm.getSchema();
switch ((int)oldVersion){
// case 0:{
// RealmObjectSchema personSchema = schema.get("User");//获取表

// personSchema
// .addField("outerId", String.class)//添加字段
// .transform(new RealmObjectSchema.Function() {
// @Override
// public void apply(DynamicRealmObject obj) {
// obj.set("outerId", "1");//为id设置默认值
// }
// });
.removeField("age");//移除age属性
// //注意version不要break,因为前面的版本都要升级
// }

可以看到,版本升级的部分隐藏了,如果在User中添加一个outerId字段,然后修改数据库版本0->1,可以打开这部分看看效果,我试过了,是可用的。

然后,看下增删改查怎么写:

public class UserDao implements BaseDao<User> {
private UserDao(){
}

private Realm getRealm(){
return DBUtil.getIntance().getRealm();
}

private static UserDao dao;
public static UserDao getInstance(){
if(dao == null)
dao = new UserDao();
return dao;
}

@Override
public void insert(final User user) throws Exception {
getRealm().executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
User u = realm.createObject(User.class);
u.setId(user.getId());
u.setName(user.getName());
}
});
}

@Override
public List<User> find() throws Exception {

List<User> mlist = null;
mlist = getRealm().where(User.class).findAllSorted("id", Sort.ASCENDING);
return mlist;
}

@Override
public void update(final User user) throws Exception {
getRealm().executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.insertOrUpdate(user);
}
});
}

@Override
public void delete(final String id) throws Exception {
getRealm().executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
RealmResults<User> result = realm.where(User.class).equalTo("id", id).findAll();
if(result!=null)
result.deleteAllFromRealm();
}
});

}

@Override
public void close() {
getRealm().close();
}

//分页查询
public static <E extends RealmModel> List<E> getLimitList(RealmResults<E> data, int offset, int limit) {
List<E> obtainList = new ArrayList();
Realm realm = Realm.getDefaultInstance();
if (data.size() == 0 ){
return obtainList;
}
for (int i = offset; i < offset + limit; i++) {
if (i >= data.size()) {
break;
}
E temp = realm.copyFromRealm(data.get(i));
obtainList.add(temp);
}
realm.close();
return

//最后一个是分页,参数1realm数据,可先通过

RealmResults <User> result = realm.where(User.class).equalTo("id", id).findAll();

获取,参数2:开始的index,参数3:取出数目 例如参数2为0,参数3为20则为取出0-19的数据。注意,realm的findAll取出数据经测试,是乱序的。如果需要排序,请添加findAllSorted(“id”, Sort.ASCENDING);,其中ASCENDING是升序,DESCENDING是降序

realm.insertOrUpdate(user);

这一句表示没有该数据时插入,有该数据时更新,建议替换成下面:

User user=realm.where(User.class).equalTo("id",mId).findFirst();
user.setName(name);

注意,该部分语句要放到transaction当中
在主页的时候,退出时要注意关闭数据库:

UserDao.getInstance().close();


举报

相关推荐

0 条评论