有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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对象上声明的回调中调用该方法。然而,这似乎是很难遵循的代码


共 (2) 个答案

  1. # 1 楼答案

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

    另一方面,如果使用自己的转换器,可以在返回结果之前在主线程之外进行额外的计算

  2. # 2 楼答案

    使用flatMap()操作符将响应转换为任何对象,而不是Call使改型接口返回Single

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

    为了使改造能够返回Single,您必须在构建改造实例时添加呼叫适配器工厂:

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