使用异步改装调用

时间:2018-01-29 07:42:18

标签: java android http retrofit retrofit2

我的目标是在UI线程上调用回调之前,根据模型中的Retrofit调用结果执行一些额外的逻辑。

我故意使用改造,因为我读过它比AsyncTask更有效。我正在实现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对象而不是直接在演示者中使用改造生成的客户端的原因是我还有一个不同的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()方法,然后调用该方法在单个交换对象上声明的回调。但是,这似乎很难遵循的代码。

2 个答案:

答案 0 :(得分:1)

而不是{@janparameter} = "0" 使改造界面返回Call,而不是您能够使用Single运算符将响应转换为任何对象。

flatMap()

现在在客户端代码中:

public interface IExchange2Api {
    @GET("another_uri_zzz")
    public Single<Exchange2ObjectZZZ> getObjectZZZ();
}

为了让Retrofit能够返回api.getObjectZZZ() .flatMap(new Function<Exchange2ObjectZZZ, SingleSource<AnotherObject>>() { @Override public SingleSource<AnotherObject> apply(Exchange2ObjectZZZ objectZZZ) throws Exception { AnotherObject anotherObject = objectZZZ.toAnotherObject(); return Single.just(anotherObject); } }) ,您必须在构建改造实例时添加呼叫适配器工厂:

Single

答案 1 :(得分:0)

Retrofit是一个网络库,而Asynctask提供了一种将任务卸载到另一个线程的简单方法。除非您使用Asynctask来推广自己的网络解决方案,否则它们不是完全可互换的。因此,请继续使用您喜欢的线程解决方案。

另外,如果您使用自己的转换器,则可以在返回结果之前从主线程执行其他计算。