情境
我們在操作一些非同步行為的時候,常常會透過 LiveData 來幫忙我們監控非同步的進度,比如說,透過一個 Boolean 的監控來得知,是否要將 ProgressDialog 顯示出來。
完整程式碼
如果你需要完整程式碼,可以到 GitHub 上觀看或下載。
說明
一般來說,我們在處理非同步的時候,都會顯示一個讀取中的畫面來告知使用者,所以,我們模擬一下進行非同步時顯示讀取中的畫面。
假設你在 ViewModel 內寫了一段這樣的程式碼,假裝透過非同步讀取一個需時 2 秒鐘的任務,因此,會透過一個讀取中的 Dialog 來顯示讀取中。
class FetchViewModel : ViewModel() {
val data = MutableLiveData<String>()
val loading = MutableLiveData<Boolean>()
@SuppressLint("CheckResult")
fun fetchData() {
loading.value = true
Observable.just(1)
.subscribeOn(Schedulers.newThread())
.map {Thread.sleep(2000)}
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
loading.value = false
data.value = "done!"
}
}
}
接著你又在 MainActivity 呼叫 ViewModel 來顯示我們的資料。
send_btn.setOnClickListener {
viewModel.fetchData()
}
viewModel.loading.observe(this, Observer {
if(it){
supportFragmentManager.run {
dialog.show(this, "")
}
} else{
dialog.dismiss()
}
})
viewModel.data.observe(this, Observer {
info.text = it
})
結果如下圖。
但是,其實 RxJava 也有提供相關方法可以讓你更簡略處理這一塊。
fun fetchData() {
Observable.just(1)
.subscribeOn(Schedulers.newThread())
.map {
Thread.sleep(2000)
}
.observeOn(AndroidSchedulers.mainThread())
.compose(loading())
.subscribe {
data.value = "done!"
}
}
private fun <T> loading(): ObservableTransformer<T, T> {
return ObservableTransformer {
it.doOnSubscribe { loading.value = true }
.doFinally { loading.value = false }
}
}
透過一個 Transformer 來進行轉換,就可以利用 Compose 的方法幫我們處理掉是否要顯示讀取畫面的功能,如此一來,就可以讓程式碼專注在邏輯處理。