我对Futures还是很陌生,被困在链接调用和创建对象列表上。我正在使用Android,API最小值为19。

我想在下面编写方法getAllFoo()

ListenableFuture<List<Foo>> getAllFoo() {
    // ...
}


我有以下两种可用的方法:

ListenableFuture<Foo> getFoo(int index) {
    // gets a Foo by its index
}

ListenableFuture<Integer> getNbFoo() {
    // gets the total number of Foo objects
}


方法Futures.allAsList()在这里可以很好地工作,但是我的主要约束是对getFoo(int index)的每次调用都必须在前一个完成之前才能进行。

据我了解(并对其进行测试),Futures.allAsList()“散开”调用(所有调用同时开始),所以我不能使用类似的方法:

ListenableFuture<List<Foo>> getAllFoo() {
    // ...

    List<ListenableFuture<Foo>> allFutureFoos = new ArrayList<>();
    for (int i = 0; i < size; i++) {
        allFutureFoos.add(getFoo(i));
    }

    ListenableFuture<List<Foo>> allFoos = Futures.allAsList(allFutureFoos);

    return allFoos;
}


我有这种(难看的)解决方案(有效):

// ...
final SettableFuture<List<Foo>> future = SettableFuture.create();

List<Foo> listFoos = new ArrayList<>();
addApToList(future, 0, nbFoo, listFoos);

// ...
private ListenableFuture<List<Foo>> addFooToList(SettableFuture future, int idx, int size, List<Foo> allFoos) {

    Futures.addCallback(getFoo(idx), new FutureCallback<Foo>() {
        @Override
        public void onSuccess(Foo foo) {
            allFoos.add(foo);
            if ((idx + 1) < size) {
                addFooToList(future, idx + 1, size, allFoos);
            } else {
                future.set(allFoos);
            }
        }

        @Override
        public void onFailure(Throwable throwable) {
            future.setException(throwable);
        }
    });
    return future;
}


如何使用ListenableFuture优雅地实现它?
我发现了多个相关主题(例如thisthat),但是它们使用的是“编码”转换,而不是基于可变数量的转换。

我如何编写ListenableFutures并获得与Futures.allAsList()相同的返回值,但是要通过链接调用(扇入)来实现?

谢谢 !

最佳答案

通常,将衍生期货与transform / catching / whennAllSucceed / whenAllComplete链接在一起比与手动addListener / addCallback调用更好。转换方法可以为您做更多的事情:


提供更少的机会忘记设置输出,从而挂起程序
传播抵消
避免将内存保留超过所需的时间
做一些技巧来减少堆栈溢出的机会


无论如何,我不确定是否有一种特别优雅的方法可以做到这一点,但是我建议遵循以下原则(未经测试!):

ListenableFuture<Integer> countFuture = getNbFoo();
return countFuture.transformAsync(
    count -> {
      List<ListenableFuture<Foo>> results = new ArrayList<>();
      ListenableFuture<?> previous = countFuture;
      for (int i = 0; i < count; i++) {
        final int index = i;
        ListenableFuture<Foo> current = previous.transformAsync(
            unused -> getFoo(index),
            directExecutor());
        results.add(current);
        previous = current;
      }
      return allAsList(results);
    },
    directExecutor());

关于java - 组成可变数目的ListenableFuture,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46913218/

10-10 09:20