如何使用 RxJava Compose

如何使用 RxJava Compose

情境

我們在操作一些非同步行為的時候,常常會透過 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 的方法幫我們處理掉是否要顯示讀取畫面的功能,如此一來,就可以讓程式碼專注在邏輯處理。