版權(quán)聲明:本文來自 Crocutax 的博客 , 轉(zhuǎn)載請注明出處 http://www.crocutax.com
Realm使用注意事項(xiàng)
- Realm默認(rèn)運(yùn)行在主線程,使用時須開啟異步任務(wù)
- Realm本身是單例類,可以多線程并發(fā)調(diào)用,但是RealmObject則不允許并發(fā),每個RealmObject都綁定了一個TreadId,必須在創(chuàng)建該RealmObject的線程中使用它.
- 在子線程查詢出的數(shù)據(jù)無法在主線程使用,自己的方案是:子線程查詢,置換為自己的Bean類,然后在主線程使用
- 沒有主鍵的realmObject無法進(jìn)行update操作.所以如果要使用realm.copyToRealmOrUpdate(realmObject),那么這個realmObject必須設(shè)置primaryKey
- 如果Realm關(guān)閉决乎,所有查詢得到的RealmObject都不能使用了,解決方案是復(fù)制一份數(shù)據(jù)到內(nèi)存中峡捡。
- 操作數(shù)據(jù)庫必須在transaction中完成
常見問題
Object not managed by Realm, so it cannot be removed
Realm不支持直接通過deleteFromRealm刪除Bean類,即使該Bean extends RealmObject今艺,否則會報此異常
正確姿勢:
根據(jù)指定字段,從數(shù)據(jù)庫中查詢到該Bean枝秤,然后再刪除
/**
* 從數(shù)據(jù)庫中刪除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自帶線程保護(hù)功能,只能在創(chuàng)建它的線程中訪問戈稿,在子線程中不能訪問猾浦。
也就是說,如果你在主線程中new了一個RealmObject對象 user魄揉,那么在子線程中是訪問不了user對象的剪侮。
要想在子線程中訪問,必須先將user存入Ream中,然后在子線程中query出來瓣俯。
簡書文章
is not part of the schema for this Realm
詳細(xì)異常信息: java.lang.IllegalArgumentException: UserBean is not part of the schema for this Realm
需要調(diào)整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<E>, Object)' instead
詳細(xì)異常信息: io.realm.exceptions.RealmException: 'UserBean' has a primary key, use 'createObject(Class<E>, Object)' instead.
如果實(shí)體中已經(jīng)通過@PrimaryKey
標(biāo)明了主鍵,那么想要通過createObject(Class<E>, Object)
創(chuàng)建實(shí)體對象,則必須傳入primaryKeyValue(主鍵值)
異步查詢之坑
1.官方文檔介紹 主線程操作Realm會卡頓/阻塞線程
官方表示Realm運(yùn)行速度很快,足以在主線程運(yùn)行,而后又表示其實(shí)還是會阻塞線程導(dǎo)致偶發(fā)的ANR,因此建議在子線程操作Realm.
解決方案:
子線程查詢,置換為自己的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
詳細(xì)異常信息: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@4dffbdd rejected from io.realm.internal.async.RealmThreadPoolExecutor@c09c352[Running, pool size = 17, active threads = 2, queued tasks = 100, completed tasks = 110]
解決方案:
不要在for循環(huán)中使用Realm,將數(shù)據(jù)存入集合中,然后開啟事務(wù),直接使用copyToRealmOrUpdate(realmObjectList)存儲即可.
事務(wù)嵌套報異常
詳細(xì)異常信息: 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
原因 : 在一個事務(wù)中開啟了另外一個事務(wù).應(yīng)避免這種情況.