问题
I have writeToRealm method that I use very often. And I need to use it from different threads and cut boilerplate code. What is the better way for this task?
private boolean writeToRealm(String user, String id) {
SubscriberObject subscriber = new SubscriberObject();
if(mRealm.where(SubscriberObject.class)
.equalTo(SubscriberObject.ID,id).findAll().isEmpty()
&&mRealm.where(SubscriberObject.class)
.equalTo(SubscriberObject.USERNAME,user).findAll().isEmpty()) {
subscriber.setId(id);
subscriber.setUsername(user);
mRealm.beginTransaction();
mRealm.insert(subscriber);
mRealm.commitTransaction();
return true;
}
return false;
}
I am planning to use construction below (or something like this) but I can't create a correct construction:
public static Boolean writeToRealm(final String user,final String id){
Realm mRealm;
return Flowable.using(
mRealm = Realm.getDefaultInstance(),
new Function<Realm, Boolean>() {
@Override
public Boolean apply(@NonNull Realm realm) throws Exception {
SubscriberObject subscriber = new SubscriberObject();
if(realm.where(SubscriberObject.class)
.equalTo(SubscriberObject.ID,id).findAll().isEmpty()
&&realm.where(SubscriberObject.class)
.equalTo(SubscriberObject.USERNAME,user).findAll().isEmpty()) {
subscriber.setId(id);
subscriber.setUsername(user);
realm.beginTransaction();
realm.insert(subscriber);
realm.commitTransaction();
return true;
}
return false;
}
},
mRealm.close()).subscribeOn(Schedulers.io());
}
Or may be I need to create a thread class with looper for this task?
How to better integrate this method and similar methods into a clean architecture?
回答1:
I think you're just looking for
private boolean writeToRealm(String user, String id) {
try(Realm realm = Realm.getDefaultInstance()) {
if(realm.where(SubscriberObject.class).equalTo(SubscriberObject.ID,id).count() <= 0L
&& realm.where(SubscriberObject.class).equalTo(SubscriberObject.USERNAME,user).count() <= 0L) {
final SubscriberObject subscriber = new SubscriberObject();
subscriber.setId(id);
subscriber.setUsername(user);
realm.executeTransaction(r -> r.insert(subscriber));
return true;
}
}
return false;
}
回答2:
I think this could be way an easier solution:
public static Boolean writeToRealm(String user, String id) {
Realm realm = Realm.getDefaultInstance();
SubscriberObject subscriber = new SubscriberObject();
if (realm.where(SubscriberObject.class).equalTo("ID", id).or().equalTo("USERNAME", user).findAll().isEmpty()){
subscriber.setId(id);
subscriber.setUsername(user);
realm.beginTransaction();
realm.insert(subscriber);
realm.commitTransaction();
realm.close();
return true;
}
realm.close();
return false;
}
If you need some explainations, just tell me and I will implement it :)
PS: if I missunderstood your question, let me know!
回答3:
The asynchronous transaction support works the same way as the current executeTransaction, but instead of opening a Realm on the same thread, it will give you a background Realm opened on a different thread. You can also register a callback if you wish to be notified when the transaction completes or fails.
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
Dog dog = realm.where(Dog.class).equalTo("age", 1).findFirst();
dog.setName("Fido");
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
Log.d("REALM", "All done updating.");
Log.d("BG", t.getName());
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
// transaction is automatically rolled-back, do any cleanup here
}
});
read more
回答4:
First of all you can't have boolean return type if you want to do your transaction asynchronously. You will have to use either Interface pass result back to caller or you have to opt for some other means like RxJava.
just to give you example.
The RxJava way(As this would be simplest way):
public static Flowable<Boolean> writeToRealm(final String user,final String id) {
return Flowable.fromCallable(
new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
Realm realm = Realm.getDefaultInstance();
if(realm.where(SubscriberObject.class)
.equalTo(SubscriberObject.ID,id).findAll().isEmpty()
&&realm.where(SubscriberObject.class)
.equalTo(SubscriberObject.USERNAME,user).findAll().isEmpty()) {
SubscriberObject subscriber = new SubscriberObject();
subscriber.setId(id);
subscriber.setUsername(user);
realm.beginTransaction();
realm.insert(subscriber);
realm.commitTransaction();
mRealm.close();
return true;
}
mRealm.close();
return false;
}
});
}
You subscribe the returned Flowable on desired thread/schedular to perform transaction on that particular thread.
来源:https://stackoverflow.com/questions/46297838/realm-transaction-using-from-different-thread