2017-05-03 2 views
1

이 함수는 ArrayList에있는 모든 파일을 다운로드하고 이것을 "동기식"으로 만들고 싶습니다. 즉, 한 번에 하나의 파일 만 다운로드하려고합니다.JAVA 사이클을 콜백과 동기화

파일을 다운로드하고 다른 파일을 다운로드 할 때까지 FOR주기를 대기 상태로 만들려면 어떻게해야합니까?

public void downloadFiles(ArrayList<String> files, final String destinationFolder){ 
    for(String file:files){ 
    GoogleDrive.getInstance().readFile(file, GoogleDrive.FolderLocation.ROOT_FOLDER, new GoogleDrive.GoogleDriveReadFileCallback() { 
     @Override 
     public void successful(String title, byte[] content) { 
      try { 
      FileUtils.writeByteArrayToFile(new File(destinationFolder+File.pathSeparator+title), content); 
      } catch (IOException e) { 
      Log.e(TAG,"ERROR FileManager.downloadFiles: "+e.toString()); 
      } 
     } 
     @Override 
     public void notFound() { } 
     @Override 
     public void error(String error) { } 
     }); 
    } 
} 
+0

이상하게도 나는 보통 순차적 방식으로 작동하는 코드를 작성하기 시작합니다. 나중에 병렬 처리가 추가됩니다. 흥미로운 접근 방식으로 훨씬 더 복잡한 문제를 해결할 수 있습니다 ;-) – GhostCat

+0

API 문서에는 동기식으로 읽을 수 있는지 알려주는 것이 없습니까? 또한 콜백에서 다음 요소에 대한 읽기를 구체화 할 수 있으며 이렇게하면 모든 요청을 직렬화 할 수 있습니다. –

+0

아직도 흥미로운 질문; 내 표를 가져라! – GhostCat

답변

2

매우 간단합니다. 그러나 으로 밝혀졌습니다. 왜 그런가요? 주어진 코드가 에있는 일을하고 있기 때문에 방식이 잘못되었습니다. 그게 무슨 뜻이야?

내가

GoogleDrive.getInstance().readFile(file, 
    GoogleDrive.FolderLocation.ROOT_FOLDER, 
    new GoogleDrive.GoogleDriveReadFileCallback() 

트리거 가정 비동기 Google 드라이브에서 읽을; 그리고 시 콜백 인스턴스가 호출됩니다. 우리가 콜백 코드에 면밀한 관찰을 때 - 우리는 중요한 부분을 누락되었음을 발견 :

  • 는 오류 처리 (힌트의 어떤 종류의 일을 하지입니다 : 뭔가 갔을 때 당신이 생각이 없다 이 접근법에서 잘못됨)
  • 콜백은 "완료되었습니다"외부 세계에 "신호를 보낼"수있는 방법이 없습니다.

따라서 해결책은 그 것을 완전히 재 작업하는 것입니다. 필요한 인터페이스를 구현하는 실제 클래스를 만들 수 있습니다. 콜백 구현에는 파일 읽기가 계속 진행 중인지, 성공적으로 완료되었는지 또는 실패했는지 여부를 알려주는 메소드가있을 수 있습니다.

즉, Google 드라이브 readFile() 주위에 래퍼을 작성합니다. 랩퍼는 동기 읽기를 제공합니다 (readFile()이 완료되면 successfull()이 호출되어 래퍼가 단순히 콜백을 기다릴 수 있습니다). 또는 래퍼는 일종의 Future을 반환 할 수 있습니다.

+0

해결책이 불완전하다는 데 동의합니다. 그러나 이것이 OP가 제기 한 질문에 대한 대답이라고 생각하지 않습니다. –

+0

나는 그 자리를 때리는 것 같아. –

+0

선생님, 고마워요. – GhostCat

1

24 시간 후 answerear는 너무 쉬워서 이전 버전이 종료 될 때마다 새 다운로드를 시작하고 목록에서 제거하는 리스너를 구현했습니다. 이것이 올바른 방법인지는 모르겠지만 작동합니까?

interface FileManagerDownloadEvent{ 
    void downloadSuccessful(String fileName); 
    void downloadNotFound(String fileName); 
    void downloadError(String fileName,String error); 
} 

public class FileManager implements FileManagerDownloadEvent{ 

     private FileManagerDownloadEvent downloadEvent; 
     private ArrayList<String> filesToDownload; 
     private String destinationFolder; 

     public FileManager(){ 
      this.downloadEvent=this; 
     } 

     private void download(){ 
      if(filesToDownload.size()!=0) { 
       final String file=filesToDownload.get(0); 
       filesToDownload.remove(0); 

       GoogleDrive.getInstance().readFile(file, GoogleDrive.FolderLocation.ROOT_FOLDER, new GoogleDrive.GoogleDriveReadFileCallback() { 
        @Override 
        public void successful(String title, byte[] content) { 
         try { 
          FileUtils.writeByteArrayToFile(new File(destinationFolder+File.separator+title), content); 
          downloadEvent.downloadSuccessful(destinationFolder+File.separator+title); 
         } catch (Exception e) { 
          Log.e(TAG,"ERROR FileManager.downloadFiles: "+e.toString()); 
         } 
        } 

        @Override 
        public void notFound() { 
         downloadEvent.downloadNotFound(file); 
        } 

        @Override 
        public void error(String error) { 
         downloadEvent.downloadError(file,error); 
        } 
       }); 
      } 
     } 

     @Override 
     public void downloadSuccessful(String filePath) { 
      Log.d(TAG,"downloadSuccessful: "+filePath); 
      download(); 
     } 

     @Override 
     public void downloadNotFound(String fileName) { 
      Log.e(TAG,"downloadNotFound: "+fileName); 
      download(); 
     } 

     @Override 
     public void downloadError(String fileName,String error) { 
      Log.e(TAG,"downloadError: "+fileName+" --> "+error); 
      download(); 
     } 
    }