2017-10-24 10 views
0

저는 Futures를 처음 접했고 체인 연결에 매달려있어 객체 ​​목록을 만들었습니다. Futures.allAsList()가 잘 작동합니다ListenableFuture의 변수 번호를 구성하십시오.

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

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

방법 : 나는 가능한이 두 방법을

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

: 내가 안드로이드를 사용하고, API 분은 내가 아래의 방법 getAllFoo()를 코딩 할 19

입니다 여기,하지만 내 주된 제약은 각각의 getFoo(int index)에 대한 호출은 이전 호출이 완료 될 때까지 발생할 수 없다는 것입니다.

지금까지 내가 (그리고 그것을 테스트), Futures.allAsList() "팬 아웃"호출 (모든 통화가 동시에 시작), 그래서 나는 그런 뭔가 사용할 수 없습니다 그것을 이해 :

가 가
// ... 
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를 사용하여 :

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; 
} 
나는 (작동) (추한) 솔루션의 종류가?
여러 개의 관련 주제 (예 : this 또는 that)가 발견되었지만 "코딩 된"변환을 사용하고 있고 다양한 변형 횟수를 기반으로하지 않습니다.

ListenableFutures을 어떻게 구성하고 Futures.allAsList()과 동일한 반환 값을 얻을 수 있습니까?하지만 전화 연결 (팬 인)을 사용할 수 있습니까?

감사합니다.

+0

질문을 세 번 읽은 후에도 나는 아직도 당신이 무엇을 요구하고 있는지 알지 못합니다. –

+0

영어가 모국어가 아니며 구두 따기에 조금 어려울 수 있습니다. 나는 편집 중이다. – w00ly

답변

2

는 일반적으로, 그것은 수동 addListener/addCallback 통화보다 함께 transform/catching/whennAllSucceed/whenAllComplete 체인 파생 선물하는 것이 좋습니다. 변환 방법은 당신을 위해 좀 더 많은 작업을 수행 할 수 있습니다

  • 현재 적은 기회를 따라서
  • 가 트릭을 필요 이상으로
  • 전파 취소
  • 피하기 유지 메모리 이상 프로그램을 매달려, 출력을 설정하는 것을 잊지하기 스택 오버플로 가능성을 줄이십시오.

어쨌든 특히 이렇게 우아한 방법이 있는지 모르겠지만이 줄을 따라 뭔가를 제안합니다 (테스트되지 않음) :

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()); 
+1

코드를 내 문장으로 번역하려했지만'results.add (current)'에 오류가있다. 결국, 당신은'allAsList (results)'를 사용하고 있습니다. 그래서이 시점에 도달하면'getFoo (index)'에 대한 모든 호출이 시작되지 않을까요? 또는 transformAsync가 체인을 처리합니까? – w00ly

+0

죄송합니다. 몇 가지 수정되었습니다. 여전히 깨진 경우 다음 번에 실제로 컴파일 할 것을 약속합니다. 예,'transformAsync'는 한 번에 하나의 getFoo 호출 만 발생하도록합니다.보통 이것은 분명히 사실입니다. 변환은 입력 값을 변환 할 때까지 시작할 수 없습니다. 여기에 더 미묘합니다. 입력 값 (위의 '사용되지 않음'이라고 함)을 무시했지만 변환 값은 값을 알기 전까지는 시작되지 않습니다. –

+0

그것은 매력처럼 작동합니다! 감사합니다 @ 크리스 Povirk에 대한 편집 및 지원 :) – w00ly