주요글: 도커 시작하기
반응형

안드로이드로 앱을 개발할 때 흔히 필요한 기능이 특정 URL 이미지를 로컬 파일로 다운로드 받은 뒤에, 그 이미지를 ImageView로 출력하는 기능이다. 이미지를 다운받아 ImageView로 출력하려면 일단 이미지를 다운받아 로컬에 파일로 저장하는 기능이 필요하다.


본 글에서는 앞서 "유지보수를 고려한 안드로이드 비동기 처리 기반 코드 만들기" 글에서 비동기 처리를 위한 만들었던 AsyncExecutor를 이용해서 파일을 다운로드 하는 코드를 만들어보겠다. (앞서 글에서 AsyncExecutor의 구현을 먼저 확인해 본 뒤 본 글을 읽으면 쉽게 이해가 될 것이다.)


이 기능을 구현하기 위해 세 개의 클래스를 만들었다.

  • HttpRequestHelper: HttpClient를 이용해서 다운로드 받은 데이터를 File로 쓰는 기능 제공
  • FileDownloadCallable: AsyncExecutor에서 실행할 Callable 구현 클래스로서 HttpRequestHeloper가 제공하는 다운로드 기능을 실행
  • AsyncFileDownloader: 비동기로 파일 다운로드를 처리해주는 기능 제공

HttpRequestHelper 클래스의 파일 다운로드 기능 구현


HttpRequestHelper 클래스는 지정한 URL로부터 데이터를 읽어와 지정한 파일로 기록하는 기능을 제공한다. 다음은 구현 코드이다.


public class HttpRequestHelper {


public File download(String url, File toFile) throws IOException {

AndroidHttpClient client = AndroidHttpClient.newInstance("ANDROID");

HttpGet getRequest = new HttpGet(url);

try {

HttpResponse response = client.execute(getRequest);

checkStatusAndThrowExceptionWhenStatusIsNotOK(response);

return writeResponseToFileAndGet(response.getEntity(), toFile);

} catch (IOException e) {

getRequest.abort();

throw e;

} finally {

client.close();

}

}


private void checkStatusAndThrowExceptionWhenStatusIsNotOK(

HttpResponse response) throws IOException {

int statusCode = response.getStatusLine().getStatusCode();

if (statusCode != HttpStatus.SC_OK) {

throw new IOException("invalid response code:" + statusCode);

}

}


private File writeResponseToFileAndGet(HttpEntity entity, File toFile)

throws IOException {

InputStream in = null;

try {

IOUtils.copy(entity.getContent(), toFile);

return toFile;

} finally {

IOUtils.close(in);

entity.consumeContent();

}

}


public static HttpRequestHelper getInstance() {

return new HttpRequestHelper();

}


}


download() 메서드는 지정한 URL을 이용해서 HttpClient를 실행한다. 응답 코드가 OK가 아니면 익셉션을 발생시키고, 정상응답인 경우 응답 데이터를 지정한 파일에 저장한다.


FileDownloadCallable 클래스 구현


FileDownloadCallable 클래스는 AsyncExecutor가 비동기로 실행할 기능을 제공한다. FileDownloadCallable의 call() 메서드는 앞서 구현한 HttpRequestHelper의 download() 기능을 실행하고 그 결과를 리턴한다.


public class FileDownloadCallable implements Callable<File> {


private String url;

private File file;


public FileDownloadCallable(String url, File file) {

this.url = url;

this.file = file;

}


@Override

public File call() throws Exception {

return HttpRequestHelper.getInstance().download(url, file);

}


}


AsyncFileDownloader 클래스 구현


AsyncFileDownloader 클래스는 AsyncExecutor와 FileDownloadCallable을 이용해서 비동기로 파일을 다운받아 저장한다. 아래 코드는 구현 코드이다.


public class AsyncFileDownloader {


private Context context;


public AsyncFileDownloader(Context context) {

this.context = context;

}


public void download(String url, AsyncCallback<File> callback) {

download(url, null, callback);

}


public void download(String url, File destination, AsyncCallback<File> callback) {

try {

destination = getDestinationIfNotNullOrCreateTemp(destination, callback);

} catch (IOException e) {

callback.exceptionOccured(e);

return;

}

runAsyncDownload(url, destination, callback);

}


private File getDestinationIfNotNullOrCreateTemp(File destination,

AsyncCallback<File> callback) throws IOException {

if (destination != null) {

return destination;

}

return createTemporaryFile();

}


private File createTemporaryFile() throws IOException {

return File.createTempFile("afd", ".tmp", context.getCacheDir());

}


private void runAsyncDownload(String url, File destination, AsyncCallback<File> callback) {

Callable<File> callable = new FileDownloadCallable(url, destination);

new AsyncExecutor<File>().setCallable(callable).setCallback(callback).execute();

}


}


AsyncFileDownloader의 download() 메서드는 다운로드 받을 URL(url 파라미터), 다운받은 파일을 보관할 경로(destination 파라미터), 그리고 파일 다운이 완료될 때 호출할 콜백(callback 파라미터)를 전달받는다. download() 메서드의 실행 순서는 다음과 같다.

  • getDestinationIfNotNullOrCreateTemp() 메서드를 이용해서 destination이 null 이면 임시 파일을 생성한다.
    • 임시 파일을 생성하는 도중에 익셉션이 발생하면 callback 객체에 에러 사실을 알리고 종료한다.
    • 임시 파일은 캐시 디렉토리에 생성한다.
  • runAsyncDownload() 메서드를 실행해서 비동기 다운로드를 실행한다.
runAsyncDownload() 메서드는 AsyncExecutor 객체를 이용해서 비동기로 파일 다운로드를 처리한다.


AsyncFileDownloader 사용해서 다운로드 파일 사용하기


다음 코드는 AsyncFileDownloader의 사용 예이다.


public class DetailActivity extends Activity {

...

private void downloadFile() {

new AsyncFileDownloader(this).download(someImageUrl, fileDownCallback);

}


private AsyncCallback<File> fileDownCallback = new AsyncCallback.Base<File>() {

@Override

public void onResult(File result) {

// result 파일을 사용해서 처리

}


@Override

public void exceptionOccured(Exception e) {

// 익셉션 처리

}

};



관련 자료



+ Recent posts