我正在寫一些代碼插入一個記錄到Sqlite數據庫(如果表是空的)。在插入任何數據之前,它會使Web服務調用返回一些數據。RxJava - 操作員是一項任務還是整個鏈條都是一項任務?
我正在使用SqlBrite進行數據庫訪問和對Web訪問進行改造。這是我的代碼:
Observable.just(LoveToDo.briteDatabase())
.map(new Func1<BriteDatabase, Integer>() {
@Override
public Integer call(BriteDatabase briteDatabase) {
Cursor cursor = briteDatabase.query("SELECT * FROM Accounts");
try {
return cursor.getCount();
} finally {
cursor.close();
}
}
})
.flatMap(new Func1<Integer, Observable<Person>>() {
@Override
public Observable<Person> call(Integer count) {
if (count == 0) {
return LoveToDo.basecampClient().fetchMe();
}
return null;
}
})
.map(new Func1<Person, Boolean>() {
@Override
public Boolean call(Person person) {
if (person == null) return false;
BriteDatabase database = LoveToDo.briteDatabase();
long count = database.insert(Account.TABLE, new Account.Builder()
.accountId(Settings.accountId)
.userName(Settings.userName)
.password(Settings.password)
.agent(Settings.agent)
.personId(person.id)
.build()
);
return count > 0;
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe();
不用說,我不認爲這是很棒的代碼。我想要做的是發現如何將此代碼轉換爲好的代碼。所以讓我們用它來挑選它的可怕性。
首先,我應該將數據庫和Web服務調用操作合併到一個運算符中。例如:
Observable.just(LoveToDo.briteDatabase())
.flatMap(new Func1<BriteDatabase, Observable<Person>>() {
@Override
public Observable<Person> call(BriteDatabase briteDatabase) {
Cursor cursor = briteDatabase.query("SELECT * FROM Accounts");
int count;
try {
count = cursor.getCount();
} finally {
cursor.close();
}
if (count == 0) {
return LoveToDo.basecampClient().fetchMe();
}
return null;
}
})
.map(new Func1<Person, Boolean>() {
@Override
public Boolean call(Person person) {
if (person == null) return false;
BriteDatabase database = LoveToDo.briteDatabase();
long count = database.insert(Account.TABLE, new Account.Builder()
.accountId(Settings.accountId)
.userName(Settings.userName)
.password(Settings.password)
.agent(Settings.agent)
.personId(person.id)
.build()
);
return count > 0;
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe();
或者是有一個很好的理由,以保持鏈分離出這樣的操作?
錯誤的第二件事是這是一個後臺操作 - 沒有用戶界面將作爲此代碼的結果直接更新。這就是爲什麼有一個無參數的subscribe()
函數調用。但是,當發生異常時會發生什麼?這是否意味着我不得不做類似以下的事情?
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
// Do nothing
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
// Do something with the exception
}
});
順便說一句,我還需要subscribeOn
時observeOn
設置爲後臺線程?
第三,鏈是用SqlBrite觀察者啓動的。在後面的鏈中,我需要再次使用SqlBrite,所以我使用單例LoveToDo.briteDatabase()
訪問它。這是一個壞主意嗎?有一個更好的方法嗎?
最後,有沒有什麼辦法可以break;
這個鏈?如果我可以放棄我在做的事情,而不是在每一步檢查丟失的數據,這將是很好的
至於1點,你會考慮的第一個代碼代碼片段比第二個代碼片段更合適? – Mitkins
@Camel更新了我的答案 – Diolor
謝謝。您提供的示例代碼看起來乾淨而簡單。它還解決了單例問題,並回答了問題的主要觀點:是否可以將邏輯塊放入單個運算符中?所以現在我認爲這個問題的答案是,「是的,如果它讓代碼更容易閱讀/管理」。在這種情況下,我認爲答案是「是」 – Mitkins