java通过异步改造调用在模型中执行附加逻辑
我的目标是在UI线程上调用回调之前,根据模型中改装调用的结果执行一些额外的逻辑
我有意识地使用改型,因为我读到它比异步任务更高效。我正在实现一个MVP设计模式
以下是我试图实现的目标,其中包含一些我已经拥有的代码片段,以及一些我希望能够实现的注释。 主持人:
public class Presenter {
private IView view;
private IModel model;
public void onGetPrice(ExchangeType exchangeType) {
Call<Double> call = model.getPrice(exchangeType);
call.enqueue(new Callback<Double>() {
@Override
public void onResponse(Call<Double> call, Response<Double> response) {
// Assuming success
this.view.updatePrice(response.body())
}
...
});
}
}
模型的实施:
public class Model implements IModel {
private HashMap<ExchangeType, BaseExchange> exchangeMap; //Initialized elsewhere
@Override
public Call<double> getPrice(ExchangeType exchangeType) {
return exchangeMap.get(exchangeType).getPrice();
}
}
BaseExchange的一个实现:
public abstract BaseExchange {
public abstract Call<Double> getPrice();
}
public interface IExchange1Api {
@GET("some_uri")
public Call<Exchange1ObjectA> getObjectA();
}
public class Exchange1ObjectA {
public double Price;
...
}
public class Exchange1 {
private IExchange1Api apiClient; // Initialized elsewhere using retrofit.
@Override
public Call<Double> getPrice() {
Call<Exchange1ObjectA> call = apiClient.getObjectA();
// How to convert Call<Exchange1ObjectA> to Call<Double>? The double
// value that needs to be returned is based on Exchange1ObjectA.Price,
// though needs some additional logic done.
}
}
之所以需要一个BaseExchange对象,而不是直接在presenter中使用改造生成的客户端,是因为我还有一个不同的BaseExchange实现
public interface IExchange2Api {
@GET("another_uri_zzz")
public Call<Exchange2ObjectZZZ> getObjectZZZ();
}
public class Exchange2ObjectZZZ {
public double Price;
... // Properties that are very different from Exchange1ObjectA,
// since this and Exchange1ObjectA represent fundamentaly different concepts.
}
public class Exchange2 {
private IExchange2Api apiClient; // Initialized elsewhere using retrofit.
@Override
public Call<Double> getPrice() {
Call<Exchange2ObjectZZZ> call = apiClient.getObjectZZZ();
// How to convert Call<Exchange1ObjectZZZ> to Call<Double>? The double
// value that needs to be returned is based on Exchange1ObjectZZZ.Price,
// though needs some additional logic done.
}
}
从本质上讲,在每个交换上获取价格的方式根本不同,每个交换的API返回的响应对象无法通过基类进行标准化。Exchange2ObjectZZZ代表了与Exchange1ObjectA不同的业务逻辑概念;碰巧这两个价格都符合要求。此外,Exchange2ObjectZZZ可能会以一种非常不同的方式用于另一次对交易所的呼叫,该呼叫根本不涉及价格
我一直在思考如何解决这个问题,而不必在演示者中重复大量代码,也不必创建大量贫乏的接口/DTO。我完全可以看到的另一种方法是,我将lambda传递给模型的getPrice()方法,该方法被传递给exchange的getPrice()方法,然后在单个exchange对象上声明的回调中调用该方法。然而,这似乎是很难遵循的代码
# 1 楼答案
改装是一个网络库,而Asynctask提供了一种将任务卸载到另一个线程的简单方法。除非您使用Asynctask推出自己的网络解决方案,否则它们并不完全可以互换。所以,继续使用你喜欢的线程解决方案
另一方面,如果使用自己的转换器,可以在返回结果之前在主线程之外进行额外的计算
# 2 楼答案
使用
flatMap()
操作符将响应转换为任何对象,而不是Call
使改型接口返回Single
现在在客户端代码中:
为了使改造能够返回
Single
,您必须在构建改造实例时添加呼叫适配器工厂: