Hello.
I want to fetch data from table by one row, do some operations and if it's ok delete this row.
my code is
final Realm realm = Rlm.getInstance(Rlm.Db.Analytics);
realm.where(AnalyticsQueue.class).findAllAsync().asObservable()
.filter(new Func1<RealmResults<AnalyticsQueue>, Boolean>() {
@Override
public Boolean call(RealmResults<AnalyticsQueue> analyticsQueues) {
return analyticsQueues.isLoaded();
}
})
.flatMap(new Func1<RealmResults<AnalyticsQueue>, Observable<AnalyticsQueue>>() {
@Override
public Observable<AnalyticsQueue> call(RealmResults<AnalyticsQueue> analyticsQueues) {
return Observable.from(analyticsQueues);
}
}).doOnUnsubscribe(new Action0() {
@Override
public void call() {
if (!realm.isClosed()){
realm.close();
}
}
})
.....
.subscribe(new Action1<AnalyticsQueue>() {
@Override
public void call(final AnalyticsQueue analyticsQueue) {
// some code
if (ok){
// there is three variants of code, listed below
}
}
});
event.deleteFromRealm();
// rx.exceptions.OnErrorNotImplementedException: Changing Realm data can only be done from inside a transaction.
2.
final Realm realm = Rlm.getInstance(Rlm.Db.Analytics);
realm.beginTransaction();
analyticsQueue.deleteFromRealm();
realm.commitTransaction();
// W/REALM: Mixing asynchronous queries with local writes should be avoided. Realm will convert any async queries to synchronous in order to remain consistent. Use asynchronous writes instead. You can read more here: https://realm.io/docs/java/latest/#asynchronous-transactions
3.
final Realm realm = Rlm.getInstance(Rlm.Db.Analytics);
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
event.deleteFromRealm();
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
if (!realm.isClosed()) {
realm.close();
}
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
error.printStackTrace();
if (!realm.isClosed()) {
realm.close();
}
}
});
// java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
So, how can I solve my problem?
As the warning says, if you use the async API, then you shouldn't be making synchronous writes.
If you want to do synchronous writes, then you should use the sync API for the query:
realm.where(AnalyticsQueue.class).findAll().asObservable()
And then use the 2) proposition with begin/commit replaced by executeTransaction(), without the additional getInstance() call.
I'm also thinking about how you could create an Observable on the io() scheduler that creates a Realm and passes it along in a tuple (like android.util.Pair) and then closes it, but it's just a vague idea and I can't seem to get it right (I don't really use Rx). That way you could bring the deletion to a definite background thread.
In 3), if you do
final Realm realm = Rlm.getInstance(Rlm.Db.Analytics);
final String id = event.getId();
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.where(AnalyticsQueue.class).where("id", id).findFirst().deleteFromRealm();
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
if (!realm.isClosed()) {
realm.close();
}
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
error.printStackTrace();
if (!realm.isClosed()) {
realm.close();
}
}
});
It should work.
Thanks for your replies, I resolve my problem.
@morder
It's great to hear your issue is resolved. I'm closing this for now. When the issue arises again, please reopen it. Thanks!
Most helpful comment
In 3), if you do
It should work.