비동기로 파일을 다운로드 후 해당 파일을 로드하는 로직을 코루틴으로 작성하면 아래와 비슷한 로직으로 구성이 될것이다.
CoroutineScope(Dispatchers.IO).launch { // CoroutineScope를 IO스레드에서 launch
if (downloadAsync(filePath, fileUrl)) { // 다운로드 코루틴메서드 다른 쓰레드에 영향을 주지 않는다.
loadFromLocal(file, loadListener) // 다운로드가 성공하면 다운로드된 파일을 로드한다.
}
}
downloadAsync가 파일을 다운로드하는 코루틴 메서드로 suspend키워드와 coroutineScope을 지정하여
다른 스레드에 영향을 주지 않고 동작하게 한다.
suspend fun downloadAsync(filePath: String, fileUrl: String): Boolean = coroutineScope {
if (L.DBG) {
Log.v(TAG, "downloadAsync : $filePath, $fileUrl")
}
return@coroutineScope download(filePath, fileUrl)
}
이걸 CompletableFuture에서 사용하고자 한다면 아래와 같은 형태가 될것이다.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
downloadAsync2(filePath, fileUrl)
.thenAccept { r ->
if (r) {
loadFromLocal(file, loadListener)
}
}
}
downloadAsync2는 CompletableFuture를 반환하며 thenAccept로 콜백을 받아서 처리할 수 있다.
@RequiresApi(Build.VERSION_CODES.N)
fun downloadAsync2(filePath: String, fileUrl: String): CompletableFuture<Boolean> {
return CompletableFuture.supplyAsync {
return@supplyAsync download(filePath, fileUrl)
}
}
두가지 코드는 완전히 동일하게 동작한다.
어떤게 더 좋아 보이는가??
난 개인적으로 코루틴이 나아 보인다.
왜냐하면 CompletableFuture의 경우 안드로이드 N부터 지원하는데다 코루틴이 좀더 사용이 쉽다.