[英]Emit single item while update UI about progress in RxJava / RxAndroid
我目前正在嘗試在 Android 中學習 RxJava。 我需要一些指南。 目前,我正在嘗試將下面的 AsyncTask 重寫為 RxJava:
public class MyAsyncTask extends AsyncTask<Void, ProgressInfo, Result> {
@Override
protected Result doInBackground(Void... void) {
//Long running task
publishProgress(progressInfo);
//Long running task
return result;
}
@Override
protected void onProgressUpdate(ProgressInfo... progressInfo) {
//Update the progress to UI using data from ProgressInfo
}
@Override
protected void onPostExecute(Result res) {
//Task is completed with a Result
}
}
在上面顯示的 AsyncTask 方法中,我可以通過使用onProgressUpdate
方法更新有關進度的 UI,我將所需的每個數據打包到ProgressInfo
中並在onProgressUpdate
中反映 UI。 任務結束后, Result
將從doInBackground
傳遞到onPostExecute
。
但是,當我試圖用 RxJava 實現它時,我很難處理它。 由於我無法將任何參數傳遞給 Observer 中的onComplete
。 因此,我最終完成了以下實施。 我將ProgressInfo
和Result
的傳遞合並到onNext
中。
Observable.create(emitter -> {
//Long running task
emitter.onNext(progressInfo);
//Long running task
emitter.onNext(result);
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object -> {
if(object instanceof ProgressInfo){
//Update the progress to UI using data from ProgressInfo
}else if(object instanceof Result){
//Task is completed with a Result
}
});
問題 1:我在 RxJava 中的實現/概念是對還是錯?
雖然它有效,但我個人覺得上面的實現對我來說很奇怪和錯誤。 由於任務最終只是嘗試進行一些計算並得出一個單一的項目 - Result
。 ProgressInfo
的發射就像一個“側面”的東西,而不是“主要”的東西。 我應該用 Single.create() 來實現它。 但是如果我這樣做了,我想不出任何方法可以將任何ProgressInfo
傳遞給我的 UI。
問題 2:在更新 UI 的過程中,是否有更好的想法/方式來發出單個項目?
如果是,你將如何在 RxJava 中實現這個邏輯? 你能告訴我你的代碼/例子嗎?
問題 1:我在 RxJava 中的實現/概念是對還是錯?
當然,這取決於您的用例。 如果您想對每個進度步驟提供反饋,據我所知,沒有辦法以不同的方式進行。 當任務需要相當長的時間並且您能夠提供有意義的進度信息時,我會建議提供進度反饋。
在一種類型中使用 ProgressInfo 和 Result 的並集並測試 null 或使用從 ProgressInfo 和 Result 繼承的標記接口。
interface ResultT { }
final class ProgressInfo implements ResultT { }
final class Result implements ResultT { }
當結果通過 onNext 發出時,我會建議完成 observable,以便通知訂閱者任務已經完成。 訂閱者將通過 onNext 和之后的 onComplete 接收結果。
Observable.<ResultT>create(emitter -> {
emitter.onNext(progressInfo);
emitter.onNext(result);
emitter.onComplete();
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object -> {
if (object instanceof ProgressInfo) {
//Update the progress to UI using data from ProgressInfo
} else if (object instanceof Result) {
//Task is completed with a Result
}
});
如果您沒有有意義的進度信息,我建議您使用 Single。
問題 2:在更新 UI 的過程中,是否有更好的想法/方式來發出單個項目?
可以使用 doOn*-Operators 在訂閱和終止時更新 UI。 這種方式是最簡單的方式之一,但當來自其他訂閱的事件與 UI 更改交錯時可能會導致問題^1
.doOnSubscribe(disposable -> {/* update ui */})
.subscribe(s -> {
// success: update ui
},
throwable -> {
// error happened: update ui
},
() -> {
// complete: update ui
});
我的建議是通過 class 和訂閱方法中的 switch-case 對所有狀態(例如成功/錯誤)進行建模(參見 ^1)。 首先發出一個 StartProgress 事件,然后是 ProgressInformation 事件,然后完成 SucessResult。 使用 onError*-operators 捕獲任何錯誤並返回 FailureResult,其中包含錯誤消息和可能的 throwable。
Observable.<ResultT>create(emitter -> {
emitter.onNext(progressInfo);
emitter.onNext(result);
emitter.onComplete();
}).startWith(new StartProgress())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.onErrorReturn(throwable -> new FailureResult(throwable))
.subscribe(object -> {
// when StartProgress -> updateUI
// when ProgressInformation -> updateUI
// ...
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.