資料監聽和RX(Data Observers and Reactive Extensions)
通過以下方式,ObjectBox可以讓您的應用輕鬆應對資料變更:
- 資料監聽(data observers)
- Reactive extensions
- Rxjava的適配庫
資料監聽
第一個例子:
//第一條語句建立一個常規查詢來獲取未完成的 Task 物件。
Query<Task> query = taskBox.query()
.equal(Task_.complete,false)
.build();
// 第二條將觀察者連線到查詢。
query.subscribe(subscriptions)
.on(AndroidScheduler.mainThread())
.observer(data -> updateUi(data));
複製程式碼
- 查詢在後臺執行
- 一旦查詢完成,觀察者獲得結果資料
- 以後未完成物件如果有更改時 ,查詢將再次執行
- 一旦查詢結果有變化,它們被傳遞給觀察者
- 觀察者在Android的主執行緒上被呼叫
subscribe(subscriptions):這是一個所有訂閱的集合,如果你想要停止觀察,可以呼叫cancel()來取消。
Data Observers Basics
當物件改變時,ObjectBox通知訂閱的資料觀察者。觀察者可以訂閱某些物件型別的更改(通過BoxStore)或查詢結果。
首先,要建立資料觀察者,您需要實現io.objectbox.reactive.DataObserver介面:
public interface DataObserver<T> {
void onData(T data);
}
複製程式碼
這個觀察者在兩種情況下被ObjectBox呼叫:
- 訂閱之後
- 資料變更
onData() 被非同步執行緒呼叫,並且執行緒解耦(呼叫執行緒不是 引起資料變化的執行緒,比如:不是提交修改事務的執行緒,請記住)
觀察全部變化
BoxStore允許 DataObserver 訂閱物件型別。假設您想觀察 待辦事項列表應用的Task 物件:
DataObserver<Class> taskObserver = ...;
boxStore.subscribe(Task.class).observer(taskObserver);
複製程式碼
資料庫中Task Box有任何改變則會呼叫taskObserver 。 注意:還有 不帶任何引數的subscribe()。它訂閱觀察者以接收所有可用物件類的更改。
觀察查詢
ObjectBox讓你建立查詢 來找到符合特定條件的物件。
查詢是ObjectBox的重要組成部分:只要您需要特定的一組資料,您就需要使用查詢。
將查詢和觀察者結合在一起會產生一個方便而強大的工具:當相關資料發生變化時,查詢觀察者將自動提供新的結果。假設您在應用中顯示待辦任務列表。您可以使用 DataObserver 獲取尚未完成的所有任務,並將其傳遞給方法 updateUi ()(請注意,我們在此使用lambda語法):
Query query = taskBox.query().equal(Task_.completed, false).build(); subscription = query.subscribe().observer(data -> updateUi(data));
那麼我們的觀察者什麼時候被呼叫?觀察者訂閱時,查詢將在一個單獨的執行緒中執行。一旦查詢結束,它將被傳遞給觀察者。這是對觀察者的第一次呼叫。
請注意,這種模式可以大大簡化您的程式碼:您的資料有一個地方用來更新您的使用者介面。沒有單獨的初始化程式碼,沒有重發的事件,沒有重建的查詢等。
取消訂閱
observer()方法會返回 io.objectbox.reactive.DataSubscription介面的實現:
public interface DataSubscription {
void cancel();
boolean isCanceled();
}
複製程式碼
所以,如果你打算取消觀察,可以儲存DataSubscription,呼叫 cancel() 讓ObjectBox去掉該觀察者:
DataSubscription subscription = boxStore.subscribe().observer(myObserver);
// At some later point:
subscription.cancel();
複製程式碼
由於您可能有多個查詢訂閱,我們推薦使用 DataSubscriptionList 來儲存多個 DataSubscription 物件。基本模式是這樣的:
private DataSubscriptionList subscriptions = new DataSubscriptionList();
protected void onStart() {
super.onStart();
Query<X> query = box.query()... .build();
query.subscribe(subscriptions)... .observe(...);
}
protected void onStop() {
super.onStop();
subscriptions.cancel();
}
複製程式碼
注意:在Android上,您通常會在onCreate()/ onStart()/ onResume()生命週期方法之一中建立訂閱,並在其對應的onDestroy()/ onStop()/ onPause()中取消 訂閱 。
觀察者和事務
觀察者通知發生在事務提交後。對於某些場景,瞭解事務邊界尤為重要。如果呼叫put 或 remove,隱式事務被啟動並提交。
例如,這段程式碼會觸發兩次User上的資料觀察者:
box.put(friendUser);
box.put(myUser);
複製程式碼
有幾種方法可以將多個操作組合到一個事務中,例如使用 BoxStore類中的 runInTx() 或 callInTx()方法之一。對於我們的簡單例子,我們可以簡單地使用put()接受多個物件的過載方法:
box.put(friendUser, myUser);
複製程式碼
這隻會產生一個事務,從而發出一個 DataObserver 通知。
Reactive Extensions(RX)
ObjectBox為大多數功能提供了簡單和方便的RX。雖然其中大部分是受RxJava的啟發,但實際上並不是基於RxJava。ObjectBox帶來了自己的特性,因為並不是所有的開發人員都熟悉RxJava(對於RxJava ObjectBox庫見下文)。我們不想強加RxJava(〜10k方法)的複雜性(Rx幾乎就像學習一種新的語言)和大小。所以,讓我們現在保持簡單和整潔。
執行緒切換
ObjectBox允許將觀察者從後臺執行緒切換到主執行緒。我們來看看上面的待辦任務示例的修訂版本:
Query<Task> query = taskBox.query().equal(Task_.complete, false).build();
query.subscribe().on(AndroidScheduler.mainThread())
.observer(data -> updateUi(data));
複製程式碼
on()方法是告訴ObjectBox我們的觀察者被呼叫的執行緒。 AndroidScheduler.mainThread () 是一個內建的排程器實現。您可以 使用自定義 Looper建立 AndroidScheduler,或者實現io.objectbox.reactive.Scheduler介面來自定義一個執行緒切換。
資料變換
也許你想在將資料交給觀察者之前進行資料轉換。比方說,你想跟蹤每種型別的所有儲存物件的總數。BoxStore subscription 返回Class資訊,這個例子展示瞭如何將它們轉化為實際的總數:
boxStore.subscribe()
.transform(clazz -> return boxStore.boxFor(clazz).count())
.observer(count -> updateCount(count));
複製程式碼
這段transform程式碼將class資訊變換為總數,所以DataObserver 在onData()中將接受 Long作為引數 。
這段transform程式碼將class資訊變換為總數,所以DataObserver 在onData()中將接受 Long作為引數 。
雖然lambda語法非常簡潔,但我們還是來看一下io.objectbox.reactive.Transformer介面:
public interface DataTransformer<FROM, TO> {
TO transform(FROM source) throws Exception;
}
複製程式碼
- 實際上型別可以不變。從技術上講,可以在Transformer中處理一些資料然後發出去,(私貨:例如過濾等等)
- Transformer是非同步執行。可以執行一些耗時操作。
異常
也許你注意到變換實現可能會丟擲任何型別的異常。此外, DataObserver 可能會引發 RuntimeException。在這兩種情況下,您都可以實現 ErrorObserver :io.objectbox.reactive.ErrorObserver 以收到異常:
public interface ErrorObserver {
void onError(Throwable th);
}
複製程式碼
在subscribe()之後呼叫它們,實現方式如下:
query.subscribe().onError(new ErrorObserver() {
@Override
public void onError(Throwable th) {
}
}).observer(...)
複製程式碼
執行緒概述
如前所說,執行緒總結如下:
- 查詢執行在後臺執行緒上執行(僅限於此任務)
- DataTransformer 在後臺執行緒上執行(僅限於此任務)
- 除非通過 on()方法指定執行緒,否則 DataObserver 和 ErrorObserver都將在後臺執行緒上執行 。