2017-09-19 49 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