Android Realm数据库使用总结及采坑记录
文章目录
- Realm使用注意事项
- 常见问题
- Object not managed by Realm, so it cannot be removed
- Realm accessed from incorrect thread
- is not part of the schema for this Realm
- {bean}has a primary key, use 'createObject(Class, Object)' instead
- 异步查询之坑
- RejectedExecutionException
- 事务嵌套报异常
Realm使用注意事项
- Realm默认运行在主线程,使用时须开启异步任务
- Realm本身是单例类,可以多线程并发调用,但是RealmObject则不允许并发,每个RealmObject都绑定了一个TreadId,必须在创建该RealmObject的线程中使用它.
- 在子线程查询出的数据无法在主线程使用,自己的方案是:子线程查询,置换为自己的Bean类,然后在主线程使用
- 没有主键的realmObject无法进行update操作.所以如果要使用realm.copyToRealmOrUpdate(realmObject),那么这个realmObject必须设置primaryKey
- 如果Realm关闭,所有查询得到的RealmObject都不能使用了,解决方案是复制一份数据到内存中。
- 操作数据库必须在transaction中完成
常见问题
Object not managed by Realm, so it cannot be removed
Realm不支持直接通过deleteFromRealm删除Bean类,即使该Bean extends RealmObject,否则会报此异常
正确姿势:
根据指定字段,从数据库中查询到该Bean,然后再删除
/** * 从数据库中删除CollectBean * @param conType * @param relateId */public void deleteCollectBeanByTypeAndId(String conType,int relateId){ Realm realm = RealmUtils.getInstance().mRealm; CollectBean bean = realm.where(CollectBean.class) .equalTo(CollectBean.CON_TYPE, conType) .equalTo(CollectBean.RELATE_ID,relateId) .findFirst(); realm.beginTransaction(); bean.deleteFromRealm(); realm.commitTransaction();}
Realm accessed from incorrect thread
RealmObject自带线程保护功能,只能在创建它的线程中访问,在子线程中不能访问。
也就是说,如果你在主线程中new了一个RealmObject对象 user,那么在子线程中是访问不了user对象的。
要想在子线程中访问,必须先将user存入Ream中,然后在子线程中query出来。
简书文章
is not part of the schema for this Realm
详细异常信息: java.lang.IllegalArgumentException: UserBean is not part of the schema for this Realm
需要调整plugin中的顺序,如下:
apply plugin: 'com.android.application'apply plugin: 'com.bugtags.library.plugin'apply plugin: 'android-apt'apply plugin: 'realm-android'apply plugin: 'com.neenbedankt.android-apt'
{bean}has a primary key, use ‘createObject(Class, Object)’ instead
详细异常信息: io.realm.exceptions.RealmException: ‘UserBean’ has a primary key, use ‘createObject(Class, Object)’ instead.
如果实体中已经通过@PrimaryKey
标明了主键,那么想要通过createObject(Class
创建实体对象,则必须传入primaryKeyValue(主键值)
异步查询之坑
1.官方文档介绍 主线程操作Realm会卡顿/阻塞线程
官方表示Realm运行速度很快,足以在主线程运行,而后又表示其实还是会阻塞线程导致偶发的ANR,因此建议在子线程操作Realm.
2.子线程查询的数据,无法在主线程使用
解决方案:
子线程查询,置换为自己的Bean类,然后在主线程使用.
Realm.getDefaultInstance().executeTransactionAsync(new Realm.Transaction() { @Override public void execute(Realm realm) { Person ziPerson = realm.where(Person.class).findFirst(); personInfo = new PersonInfo(); personInfo.setName(ziPerson.getName()); personInfo.setAge(ziPerson.getAge()); //Log 输出#Execute ] false..Person{name='小明', age=18} KLog.i((Looper.getMainLooper()==Looper.myLooper())+".."+ personInfo.toString()); }}, new Realm.Transaction.OnSuccess() { @Override public void onSuccess() { //Log 输出#OnSuccess ] true..personInfo:Person{name='小明', age=18} KLog.i((Looper.getMainLooper()==Looper.myLooper())+".."+ personInfo.toString()); }}, new Realm.Transaction.OnError() { @Override public void onError(Throwable error) { KLog.i(error.toString()); }});
RejectedExecutionException
详细异常信息:java.util.concurrent.RejectedExecutionException: Task [email protected] rejected from [email protected][Running, pool size = 17, active threads = 2, queued tasks = 100, completed tasks = 110]
解决方案:
不要在for循环中使用Realm,将数据存入集合中,然后开启事务,直接使用copyToRealmOrUpdate(realmObjectList)存储即可.
事务嵌套报异常
详细异常信息:The Realm is already in a write transaction in /Users/blakemeike/Working/release/realm/realm-library/src/main/cpp/io_realm_internal_SharedRealm.cpp line 116
原因 : 在一个事务中开启了另外一个事务.应避免这种情况.
更多相关文章
- Android实现计时与倒计时(限时抢购)的几种方法(线程)
- 【Android】从主线程向子线程发消息
- android之线程访问网络并解析数据
- [Android] 任意时刻从子线程切换到主线程的实现
- Android 线程的使用(传递多个参数)
- android handler 线程机制的研究
- android listview 与 一般多线程配合产生的错误,资料汇总
- 文件多线程下载实现