Android – использование генераторов для 1 повторного вызова RxJava, возвращающего различные типы, используя тот же интерфейс

Я впервые общаюсь с 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) } 

Теперь я пытаюсь сделать общий сетевой вызов, но я не могу понять это, и задаюсь вопросом, возможно ли даже, как работает Retrofit?

Сейчас у меня есть 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() }) 

Из моего небольшого знания дженериков кажется, что я должен быть в состоянии передать общий сервис и обрабатывать столько разных концов API, используя этот один вызов RxJava? Я не знаю, как получить доступ к каждому методу getCurrentTradingInfo, и из того, что я читаю, я сомневаюсь, можно ли использовать модифицированные интерфейсы?

Я не обязательно ищу полный ответ, если это возможно (хотя объяснение было бы приятным), но мне интересно, возможно ли это сделать в этом конкретном сценарии? Я не хочу тратить свое время, если это даже невозможно.

Поэтому я смог придумать ниже, что намного лучше, чем то, что у меня было до этого. Я все еще не могу понять способ взаимодействия с интерфейсом, поэтому для каждого API есть небольшое дублирование в каждом классе xxxRepository, но намного меньше.

 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() } } 

Я бы предложил использовать 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 ; 

Это позволяет

  • быть полностью независимым от иерархии классов
  • повторно использовать тот же displayOnTicker в другом месте
  • возможно, поместите displayOnTicker в mixin?