我第一次玩Generics来清理一些重复编码的重复代码。
我能够制作一个通用的改装适配器,所以我的供应商不必每个都有一个独特的创造者,这真的很棒和令人兴奋。
private fun <T> create(service: Class<T>, baseUrl: String): T {
val retrofit = Retrofit.Builder()
.client(client)
.addConverterFactory(MoshiConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(baseUrl)
.build()
return retrofit.create(service)
}
现在我正在尝试进行通用网络通话,但我无法弄明白,并且想知道在改造是如何工作的情况下甚至是否可能?
我现在有5个服务,如下所示,所有服务都是不同的API。每个都有一个不同的端点,但都接受1个参数并返回它们的对象,这对于每个API调用略有不同。
interface ServiceA {
@GET("v2/ticker")
fun getCurrentTradingInfo(@Query("book") orderBook: String): Observable<CurrentTradingInfo>
}
所有响应对象都实现了一个接口来规范化响应数据,以便稍后显示
data class CurrentTradingInfo(val mid: String,
val bid: String,
val ask: String,
val last_price: String,
val low: String,
val high: String,
val volume: String,
val timestamp: String) : normalizedData {
override fun lastPrice(): String {
return last_price
}
override fun timeStamp(): String {
return timestamp
}
}
目前,我为每项服务进行了网络通话,如下所示
val disposable = service.getCurrentTradingInfo(ticker.ticker)
.observeOn(AndroidSchedulers.mainThread())
.repeatWhen { result -> result.delay(10, TimeUnit.SECONDS) }
.retryWhen { error -> error.delay(10, TimeUnit.SECONDS) }
.subscribeOn(Schedulers.io())
.subscribe({ result ->
val tradingInfo = TradingInfo(result.lastPrice(), result.timeStamp())
networkDataUpdate.updateData(ticker, tradingInfo)
callback.updateUi(ticker)
}, { error ->
error.printStackTrace()
})
根据我对泛型的一点知识,似乎我应该能够传递一个通用服务并使用这个RxJava调用处理尽可能多的不同API端点?我不知道如何访问每个服务getCurrentTradingInfo方法,从我读到的,我怀疑是否可以使用改造接口?
如果可能的话,我不一定要寻找完整的答案(尽管解释会很好)但是我想知道在这个具体情况下是否甚至可以做到?如果不可能,我不想浪费时间。
答案 0 :(得分:0)
所以我能够提出下面的内容比以前更好。我仍然无法找到一种解决方案,因此每个xxxRepository类中的每个API都有一些重复,但要少得多。
interface QuadrigaService {
@GET("v2/ticker")
fun getCurrentTradingInfo(@Query("book") query: String): Observable<CurrentTradingInfo>
}
class QuadrigaRepository(private val service: QuadrigaService) : BaseExchangeRepository() {
override fun feedType(): String {
return CryptoPairs.QUADRIGA_BTC_CAD.exchange
}
override fun startFeed(tickers: List<CryptoPairs>, presenterCallback: NetworkCompletionCallback, networkDataUpdate: NetworkDataUpdate) {
clearDisposables()
tickers.forEach { ticker ->
startFeed(service.getCurrentTradingInfo(ticker.ticker),
ticker, presenterCallback, networkDataUpdate)
}
}
}
使用泛型的基类
abstract class BaseExchangeRepository : Exchange {
var disposables: CompositeDisposable = CompositeDisposable()
fun clearDisposables() {
if (disposables.size() != 0) {
disposables.clear()
}
}
fun <T> startFeed(observable: Observable<T>, ticker: CryptoPairs, presenterCallback: NetworkCompletionCallback, networkDataUpdate: NetworkDataUpdate) {
val disposable = observable.observeOn(AndroidSchedulers.mainThread())
.repeatWhen { result -> result.delay(10, TimeUnit.SECONDS) }
.subscribeOn(Schedulers.io())
.subscribe({ result ->
result as NormalizedTickerData
Log.d("Result", ticker.toString() + "last price is ${result.lastPrice()}")
val tradingInfo = TradingInfo(result.lastPrice(), result.timeStamp())
networkDataUpdate.updateData(ticker, tradingInfo)
presenterCallback.updateUi(ticker)
}, { error ->
error.printStackTrace()
})
disposables.add(disposable)
}
override fun stopFeed() {
disposables.clear()
}
}
答案 1 :(得分:0)
我建议使用compose()
:
val disposable = service.getCurrentTradingInfo(ticker.ticker)
.compose(displayOnTicker(ticker))
.subscribe();
然后就在你的displayOnTicker(Source)
中(为Java主义道歉):
return source -> source
.observeOn(AndroidSchedulers.mainThread())
.repeatWhen { result -> result.delay(10, TimeUnit.SECONDS) }
.retryWhen { error -> error.delay(10, TimeUnit.SECONDS) }
.subscribeOn(Schedulers.io())
.doOnNext({ result ->
val tradingInfo = TradingInfo(result.lastPrice(), result.timeStamp())
networkDataUpdate.updateData(ticker, tradingInfo)
callback.updateUi(ticker)
})
// add .doOnError / .onErrorResumeNext as desired
;
这允许你