2017-09-19 16 views
0

我有经常使用的writeToRealm方法。我需要从不同的线程使用它并剪切样板代码。这项任务的更好方法是什么?使用不同线程的领域事务

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; 

}

我打算使用下面的施工(或像这样),但我不能创建一个正确的建设:

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()); 
    } 

或可能是我需要创建一个线程类与循环这个任务?

如何更好地将这种方法和类似的方法整合到一个干净的架构中?

+0

请喜欢使用executeTransaction()也是,产生一个新的线程,并得到一个境界对象首次被沉重的操作,我会建议你使用ExecutorService –

+0

Sarthak Mittal,我想过了,但我们仍然需要每次都创建一个实例,并且需要looper来控制更改。 – Delphian

+0

如果你需要一个非UI线程以及looper,那么HandlerThread将是最好的选择! :) –

回答

1

我认为你只是在寻找

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; 
} 
+0

EpicPandaForce感谢您的帮助和解答。我无法理解一个问题。如果我想使用不是UI线程而不使用Async方法,只使用我创建的线程,如何使用此方法?领域学院没有描述活套工作细节。例如:如果我启动新的Thread方法或Flowable.subscribeOn并将“there”writeToRealm方法(对此线程)。什么时候变更将被保存?我可以在关闭领域实例之前保存它们吗?它会在没有活套的线程中正常工作吗? – Delphian

+0

这是一个同步方法调用,没有理由使其成为可流动的。 – EpicPandaForce

+0

是的,我明白了。但是,如果我写了很多数据,我也不想使用UI线程和Async方法。例如,我开始新的线程(new Runnable ... writeToRealm)这种方法可能会产生哪些问题?在这个例子中,有必要关闭领域实例?我还在下面添加了评论。 – Delphian

0

我认为这可能是一种方式更容易的解决方案:

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; 
} 

如果你需要一些解释相关,只是告诉我,我会实现它:)

PS:如果我missunderstood你的问题,让我知道!

+0

皮尔乔治米斯莱,你能解释你的答案吗?请阅读我上面的两条评论。 – Delphian

0

异步事务支持的工作方式与当前executeTransaction相同,但不是在同一个线程上打开Realm,它会为您提供在不同线程上打开的背景Realm。如果您希望在事务完成或失败时收到通知,您还可以注册回调。

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

+0

这种方式不好,因为两个原因。第一个 - 我们应该从另一个线程控制领域实例(创建/关闭),我们可以忘记关闭它。第二个 - 异步领域池有限制。这意味着当我们的异步线程超过限制时,任务将等待。 – Delphian

0

首先,如果你希望异步做你的交易,你不能有boolean返回类型。您将不得不使用Interface传递结果返回给调用者,或者您必须选择其他方式,如RxJava。

只是为了举例。

的RxJava方式(因为这是最简单的方法):

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; 
     } 
    }); 
} 

您订阅返回所需的线程/程序器Flowable到特定线程上执行事务。

+0

Kalpesh Patel Looper怎么样?我知道如果我们在线程中没有活套,变化不会发生。我们应该控制线程是否有活套或不活动?但如何正确地做到这一点? – Delphian

+0

哪个改变你的意思? – EpicPandaForce

+0

我谈到了数据库的变化。数据库在什么时候改变?关闭或committransaction? (在非Looper线程中)例如,如果我们有2个线程 - UI和背景(非循环),从这些线程我们改变相同的元素。这将如何发生? – Delphian