java - 使用异步改造调用在模型中执行附加逻辑

标签 java android http retrofit retrofit2

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

我有目的地使用改造,因为我读到它比 AsyncTask 更高效。我正在实现 MVP 设计模式。

以下是我正在努力实现的目标,其中包含一些我已经拥有的代码 fragment ,以及一些解决我希望能够做的事情的评论。 主持人:

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 可以以非常不同的方式用于另一个完全不涉及价格的交易所调用中。

我一直在思考如何在不在演示器中复制大量代码或创建大量贫血接口(interface)/DTO 的情况下解决此问题。我完全可以看到的另一种方法是,如果我将 lambda 传递给模型的 getPrice() 方法,该方法将传递给交易所的 getPrice() 方法,然后在单个交易所对象上声明的回调中调用该方法.但是,这似乎是很难遵循的代码。

最佳答案

不是 Call 而是使 retrofit 接口(interface)返回 Single,这样您就可以使用 flatMap() 将响应转换为任何对象运营商。

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

现在在客户端代码中:

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

为了 Retrofit 能够返回 Single,您必须在构建 retrofit 实例时添加调用适配器工厂:

Retrofit restAdapter = new Retrofit.Builder()
    .baseUrl(...)
    .client(...)
    .addConverterFactory(...)
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .build();

关于java - 使用异步改造调用在模型中执行附加逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48496544/

相关文章:

java - 类型化意大利语依赖解析器

Java正则表达式,捕获格式错误的html

Android 在安装时检查网络运营商

支持印度语言的 Android 库

php - move_uploaded_file() 在 PHP 中没有按预期工作(即根本没有)

在重新启动的 Tomcat 中刷新页面后,AJAX GET 请求出现在 URL 栏中

java - HybrisContextFactory - 初始化全局应用程序上下文时出错

java - 在 jcheckbox 中使用图标而不是文本

android - 如何在所有 Activity 中实现相同的广播接收器

internet-explorer - IE7 HTTP 错误 400