编写可变数量的ListenableFuture

时间:2017-10-24 14:29:37

标签: java android guava

我对Futures很陌生,我一直坚持打电话并创建一个对象列表。我使用的是Android,API min是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()&#34;粉丝 - &#34;通话(所有通话同时开始),所以我无法使用这样的话:

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),但这些主题使用了&#34;编码&#34;变换,而不是基于可变数量的变换。

如何撰写ListenableFutures并获得与Futures.allAsList()相同的返回值,但是通过链接来电(扇入)?

谢谢!

1 个答案:

答案 0 :(得分:2)

作为一般规则,最好将衍生的期货与transform / catching / whennAllSucceed / whenAllComplete连在一起,而不是手动addListener / {{ 1}}来电。转换方法可以为您做更多的事情:

  • 目前忘记设置输出的机会较少,因此挂起程序
  • 宣传取消
  • 避免长时间保留记忆
  • 做一些技巧来减少堆栈溢出的可能性

无论如何,我不确定是否有一种特别优雅的方式来做到这一点,但我建议这些方面的东西(未经测试!):

addCallback