這是Android Weekly第270期推薦的一篇文章:How to make complex requests simple with RxJava in Kotlin,Kotlin寫的粱檀,MVP+Dagger2+RxJava2+Retrofit2陌宿,現(xiàn)在的標(biāo)配氢架。下載下來發(fā)現(xiàn)作者是用Android Studio 3.0寫的,改build.gradle中的gradle版本也跑不起來抄肖,也不想下載beta版的AS脖含,就想著自己試著寫一個,順便練習(xí)下角骤。MVP和Dagger2其實挺煩人的隅忿,所以我就怎么簡單怎么寫,達到目的就行了邦尊,還是用的Kotlin寫的(如果你說你不會kotlin背桐,那么建議趕緊學(xué)學(xué),說不定以后大牛的Demo都看不懂蝉揍,多難過傲辞汀),下面分析又沾。最后上代碼弊仪,有興趣的可以看看。
先看效果圖
這個Demo主要用的StackOverflow的開放API杖刷,就2個頁面励饵,第一個界面是請求了reputation最高的用戶并展示,第二個頁面是選擇了該用戶滑燃,展示其提的問題役听,給別人回答的答案,最喜歡的問題這三個部分表窘,每個部分只顯示3條典予。
煩人的就是第二個頁面了,該頁面是由4個接口返回的值組成的蚊丐,其中g(shù)etQuestions和getFavorites可以直接獲取到熙参,但是getAnswers返回的是答案,我們還要通過答案中的question_id再去請求對應(yīng)的問題來展示麦备。
一般的做法就是一個一個請求,再寫個方法組成沒問題,但是用RxJava中的flatmap和zip操作符能夠更加輕松的完成凛篙。
首先考慮用Single,對于Single黍匾,官網(wǎng)是這樣解釋的:
A Single is something like an Observable, but instead of emitting a series of values — anywhere from none at all to an infinite number — it always either emits one value or an error notification.
區(qū)別于Observable不同的是,Observable發(fā)出0~n個事件呛梆,而single只發(fā)出一個(事件)值:成功的值或者失敗的提示锐涯,我們就關(guān)心這2樣,相比較Observable的onNext,onComplete,onError稍微簡單些填物。
Single.zip(
ApiHelper.getService().getQuestionsByUser(mUserId),
getAnswers(),
ApiHelper.getService().getFavoritesByUser(mUserId),
Function3<CommonResult<Question>, List<Question>, CommonResult<Question>, DetailModel>
{ questionResult, answers, favoritesResult ->
val questions = questionResult.items.take(3)
val favorites = favoritesResult.items.take(3)
DetailModel(questions, answers, favorites)
}
).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
adapter.setData(it)
}, {
it.printStackTrace()
toast("請求錯誤:${it.message}")
})
zip的作用是將前三個Single發(fā)射的東西整合成一個再發(fā)射出去纹腌,看Function3,比如上面是將Single<Questions>,Single<Answers>,Single<Favorites>合成Single<DetailModel>返回滞磺,便于后續(xù)處理升薯。
getAnswers返回Single<List<Question>>,說到flatmap就想到和map的區(qū)別击困,map是將一個值轉(zhuǎn)化為另一個值涎劈,但是flatmap是將一個值轉(zhuǎn)化為一個新的Observable或者Single,再發(fā)出去阅茶,相當(dāng)于解決嵌套的問題蛛枚。下面有個注意點,用questionId去請求問題接口的話脸哀,如果把多個questionId放一起蹦浦,用;
隔開去請求就會得到一個多個問題的數(shù)組返回
private fun getAnswers(): Single<List<Question>> {
return ApiHelper.getService()
.getAnswersByUser(mUserId)
.flatMap {
val processedAnswers = it.items
.filter { it.accept }
.take(3)
val ids = processedAnswers
.map { it.questionId.toString() }
.joinToString(separator = ";")
ApiHelper.getService()
.getQuestionById(ids)
.map { it.items }
}
}
最后上自己寫的代碼地址:GitHub Repository,主要核心還是上面的zip和flatmap的使用撞蜂。代碼寫的還有很多不足的地方白筹,歡迎提出。