首页 > 解决方案 > 列出将 >10 个改造调用与 rxjava2 组合在一起的子类型转换

问题描述

我想从我的移动 android 应用程序调用我的 API 端点。

我通常使用 zip 运算符来等待最后一个操作完成,但我有 10 多个改造调用要处理,并且我发现输入到 zip 运算符的最大函数是 Function9。

我尝试传递一个可迭代对象,但我对发射器内部的类型有疑问:

@GET("/endpoint/A")
Single<List<A>> getA();

@GET("/endpoint/B")
Single<List<B>> getB();

@GET("/endpoint/C")
Single<List<C>> getC();

....

每个数据类型 A,B,C... 都实现了一个接口 Sample 以便我将 List 传递给 zip 运算符:

List<Single<List<Sample>>> callsList = new ArrayList<>();
callsList.add(apiService.getA()); // error, expected Single<List<Sample>

我试图强制演员,但也没有用

我的目标是使用 iterable 来实现这样的目标:

Single.zip(callsList, new Function<Object[], BundledData>() {
        @Override
        public BundledData apply(Object[] objects) throws Exception {
            return new BundledData(...);
        }
    })

所以我请求你的帮助:

谢谢

标签: androidlistretrofit2rx-java2

解决方案


你不能这样投。因为Single<List<A>> 不是Single<List<Sample>>. 这ASampleSingle> is not subtype ofSingle>` 的子类型。

让我给你一个简单的例子:

    List<Number> listA = new ArrayList<>();
    List<Integer> listB  = new ArrayList<>();

    listA = listB; // this line is not valid.

但这是有效的:

    Number number = 10;
    Integer integer = 20;

    number = integer;

因为Integer是 的子类型Number。并且 listA = listB;无效,因为listB不是 的子类型listA

但是您仍然可以投射它,您必须使用Wildcard.

使用通配符将类似于:

    List<? extends Number> listA = new ArrayList<>();
    List<? extends Integer> listB  = new ArrayList<>();

    listA = listB;

现在List<? extends Integer>List<? extends Number>

为了使铸造成为可能,我们需要一个共同的父母,List<Number>并且List<Integer>List<?>共同的父母。

这在官方文档中得到了很好的解释

在此处输入图像描述

虽然 Integer 是 Number 的子类型,List<Integer>但不是 Number 的子类型List<Number>,实际上这两种类型没有关系。List<Number>和的共同父项List<Integer>List<?>

为了在这些类之间创建关系,以便代码可以通过 List 的元素访问 Number 的方法,请使用上限通配符:

你的情况是一样的。您需要使用上限通配符。

List< Single< ? extends List< ? extends Sample> > > callsList = new ArrayList<>();

希望这可以帮助你。


推荐阅读