Realm transaction using from different thread

2019-08-28 09:28发布

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?

标签: android realm
4条回答
兄弟一词,经得起流年.
2楼-- · 2019-08-28 10:02

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;
}
查看更多
地球回转人心会变
3楼-- · 2019-08-28 10:02

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

查看更多
Emotional °昔
4楼-- · 2019-08-28 10:19

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!

查看更多
来,给爷笑一个
5楼-- · 2019-08-28 10:20

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.

查看更多
登录 后发表回答